added testbios for V2
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1624 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
4c5060dc2b
commit
8152126529
|
@ -0,0 +1,28 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Ix86emu/include -O2 -g
|
||||
|
||||
INTOBJS = int10.o int15.o int16.o int1a.o inte6.o
|
||||
OBJECTS = testbios.o helper_exec.o helper_mem.o $(INTOBJS)
|
||||
|
||||
LIBS = x86emu/src/x86emu/libx86emu.a
|
||||
|
||||
# user space pci is the only option right now.
|
||||
OBJECTS += pci-userspace.o
|
||||
LIBS += /usr/lib/libpci.a
|
||||
|
||||
all: testbios
|
||||
|
||||
testbios: $(OBJECTS) $(LIBS)
|
||||
$(CC) -o testbios $(OBJECTS) $(LIBS)
|
||||
|
||||
helper_exec.o: helper_exec.c test.h
|
||||
|
||||
x86emu/src/x86emu/libx86emu.a:
|
||||
$(MAKE) -C x86emu/src/x86emu/ -f makefile.linux
|
||||
|
||||
clean:
|
||||
$(MAKE) -C x86emu/src/x86emu/ -f makefile.linux clean
|
||||
rm -f *.o *~ testbios
|
||||
|
||||
distclean: clean
|
||||
$(MAKE) -C x86emu/src/x86emu/ -f makefile.linux clean
|
|
@ -0,0 +1,267 @@
|
|||
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c,v 1.16 2001/04/30 14:34:57 tsi Exp $ */
|
||||
/*
|
||||
* XFree86 int10 module
|
||||
* execute BIOS int 10h calls in x86 real mode environment
|
||||
* Copyright 1999 Egbert Eich
|
||||
*
|
||||
* Part of this is based on code taken from DOSEMU
|
||||
* (C) Copyright 1992, ..., 1999 the "DOSEMU-Development-Team"
|
||||
*/
|
||||
|
||||
/*
|
||||
* To debug port accesses define PRINT_PORT.
|
||||
* Note! You also have to comment out ioperm()
|
||||
* in xf86EnableIO(). Otherwise we won't trap
|
||||
* on PIO.
|
||||
*/
|
||||
#include <x86emu.h>
|
||||
#include "test.h"
|
||||
#include <asm/io.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
int port_rep_inb(u16 port, u32 base, int d_f, u32 count);
|
||||
u8 x_inb(u16 port);
|
||||
u16 x_inw(u16 port);
|
||||
void x_outb(u16 port, u8 val);
|
||||
void x_outw(u16 port, u16 val);
|
||||
u32 x_inl(u16 port);
|
||||
void x_outl(u16 port, u32 val);
|
||||
|
||||
/* general software interrupt handler */
|
||||
u32 getIntVect(int num)
|
||||
{
|
||||
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
|
||||
}
|
||||
|
||||
void pushw(u16 val)
|
||||
{
|
||||
X86_ESP -= 2;
|
||||
MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
|
||||
}
|
||||
|
||||
int run_bios_int(int num)
|
||||
{
|
||||
u32 eflags;
|
||||
|
||||
eflags = X86_EFLAGS;
|
||||
pushw(eflags);
|
||||
pushw(X86_CS);
|
||||
pushw(X86_IP);
|
||||
X86_CS = MEM_RW((num << 2) + 2);
|
||||
X86_IP = MEM_RW(num << 2);
|
||||
|
||||
//printf("%s: INT %x CS:IP = %x:%x\n", __FUNCTION__,
|
||||
// num, MEM_RW((num << 2) + 2), MEM_RW(num << 2));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int port_rep_inb(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -1 : 1;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
MEM_WB(dst, x_inb(port));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
int port_rep_inw(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -2 : 2;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
MEM_WW(dst, x_inw(port));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
int port_rep_inl(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -4 : 4;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
MEM_WL(dst, x_inl(port));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
int port_rep_outb(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -1 : 1;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
x_outb(port, MEM_RB(dst));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
int port_rep_outw(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -2 : 2;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
x_outw(port, MEM_RW(dst));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
int port_rep_outl(u16 port, u32 base, int d_f, u32 count)
|
||||
{
|
||||
register int inc = d_f ? -4 : 4;
|
||||
u32 dst = base;
|
||||
while (count--) {
|
||||
x_outl(port, MEM_RL(dst));
|
||||
dst += inc;
|
||||
}
|
||||
return dst - base;
|
||||
}
|
||||
|
||||
u8 x_inb(u16 port)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
val = inb(port);
|
||||
|
||||
//printf("inb(0x%04x) = 0x%02x\n", port, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u16 x_inw(u16 port)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = inw(port);
|
||||
|
||||
//printf("inw(0x%04x) = 0x%04x\n", port, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 x_inl(u16 port)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = inl(port);
|
||||
|
||||
//printf("inl(0x%04x) = 0x%08x\n", port, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void x_outb(u16 port, u8 val)
|
||||
{
|
||||
//printf("outb(0x%02x, 0x%04x)\n", val, port);
|
||||
outb(val, port);
|
||||
}
|
||||
|
||||
void x_outw(u16 port, u16 val)
|
||||
{
|
||||
//printf("outw(0x%04x, 0x%04x)\n", val, port);
|
||||
outw(val, port);
|
||||
}
|
||||
|
||||
void x_outl(u16 port, u32 val)
|
||||
{
|
||||
//printf("outl(0x%08x, 0x%04x)\n", val, port);
|
||||
outl(val, port);
|
||||
}
|
||||
|
||||
u8 Mem_rb(int addr)
|
||||
{
|
||||
return (*current->mem->rb) (current, addr);
|
||||
}
|
||||
|
||||
u16 Mem_rw(int addr)
|
||||
{
|
||||
return (*current->mem->rw) (current, addr);
|
||||
}
|
||||
|
||||
u32 Mem_rl(int addr)
|
||||
{
|
||||
return (*current->mem->rl) (current, addr);
|
||||
}
|
||||
|
||||
void Mem_wb(int addr, u8 val)
|
||||
{
|
||||
(*current->mem->wb) (current, addr, val);
|
||||
}
|
||||
|
||||
void Mem_ww(int addr, u16 val)
|
||||
{
|
||||
(*current->mem->ww) (current, addr, val);
|
||||
}
|
||||
|
||||
void Mem_wl(int addr, u32 val)
|
||||
{
|
||||
(*current->mem->wl) (current, addr, val);
|
||||
}
|
||||
|
||||
void getsecs(unsigned long *sec, unsigned long *usec)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
*sec = tv.tv_sec;
|
||||
*usec = tv.tv_usec;
|
||||
}
|
||||
|
||||
#define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00)
|
||||
#define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff)
|
||||
|
||||
u8 bios_checksum(u8 * start, int size)
|
||||
{
|
||||
u8 sum = 0;
|
||||
|
||||
while (size-- > 0)
|
||||
sum += *start++;
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
|
||||
* an attempt to detect a legacy ISA card. If they find one they might
|
||||
* act very strange: for example they might configure the card as a
|
||||
* monochrome card. This might cause some drivers to choke.
|
||||
* To avoid this we attempt legacy VGA by writing to all know VGA
|
||||
* disable registers before we call the BIOS initialization and
|
||||
* restore the original values afterwards. In beween we hold our
|
||||
* breath. To get to a (possibly exising) ISA card need to disable
|
||||
* our current PCI card.
|
||||
*/
|
||||
/*
|
||||
* This is just for booting: we just want to catch pure
|
||||
* legacy vga therefore we don't worry about mmio etc.
|
||||
* This stuff should really go into vgaHW.c. However then
|
||||
* the driver would have to load the vga-module prior to
|
||||
* doing int10.
|
||||
*/
|
||||
/*void
|
||||
LockLegacyVGA(int screenIndex,legacyVGAPtr vga)
|
||||
{
|
||||
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
|
||||
vga->save_msr = inb(0x3CC);
|
||||
vga->save_vse = inb(0x3C3);
|
||||
vga->save_46e8 = inb(0x46e8);
|
||||
vga->save_pos102 = inb(0x102);
|
||||
outb(0x3C2, ~(u8)0x03 & vga->save_msr);
|
||||
outb(0x3C3, ~(u8)0x01 & vga->save_vse);
|
||||
outb(0x46e8, ~(u8)0x08 & vga->save_46e8);
|
||||
outb(0x102, ~(u8)0x01 & vga->save_pos102);
|
||||
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
|
||||
}
|
||||
|
||||
void
|
||||
UnlockLegacyVGA(int screenIndex, legacyVGAPtr vga)
|
||||
{
|
||||
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
|
||||
outb(0x102, vga->save_pos102);
|
||||
outb(0x46e8, vga->save_46e8);
|
||||
outb(0x3C3, vga->save_vse);
|
||||
outb(0x3C2, vga->save_msr);
|
||||
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,311 @@
|
|||
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_mem.c,v 1.21 2001/05/22 16:24:37 tsi Exp $ */
|
||||
/*
|
||||
* XFree86 int10 module
|
||||
* execute BIOS int 10h calls in x86 real mode environment
|
||||
* Copyright 1999 Egbert Eich
|
||||
*/
|
||||
#define _INT10_PRIVATE
|
||||
|
||||
#define REG pInt
|
||||
#if 0
|
||||
typedef enum {
|
||||
OPT_NOINT10,
|
||||
OPT_INIT_PRIMARY,
|
||||
OPT_BIOS_LOCATION
|
||||
} INT10Opts;
|
||||
|
||||
static const OptionInfoRec INT10Options[] = {
|
||||
{OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{OPT_BIOS_LOCATION, "BiosLocation", OPTV_STRING, {0}, FALSE},
|
||||
{-1, NULL, OPTV_NONE, {0}, FALSE},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
void dprint(unsigned long start, unsigned long size)
|
||||
{
|
||||
int i, j;
|
||||
char *c = (char *) start;
|
||||
|
||||
for (j = 0; j < (size >> 4); j++) {
|
||||
char *d = c;
|
||||
printf("\n0x%lx: ", (unsigned long) c);
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%2.2x ", (unsigned char) (*(c++)));
|
||||
c = d;
|
||||
for (i = 0; i < 16; i++) {
|
||||
printf("%c", ((((u8) (*c)) > 32) && (((u8) (*c)) < 128)) ?
|
||||
(unsigned char) (*(c)) : '.');
|
||||
c++;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
#if 0
|
||||
#ifndef _PC
|
||||
/*
|
||||
* here we are really paranoid about faking a "real"
|
||||
* BIOS. Most of this information was pulled from
|
||||
* dosemu.
|
||||
*/
|
||||
void setup_int_vect(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* let the int vects point to the SYS_BIOS seg */
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
MEM_WW(i << 2, 0);
|
||||
MEM_WW((i << 2) + 2, SYS_BIOS >> 4);
|
||||
}
|
||||
|
||||
reset_int_vect(current);
|
||||
/* font tables default location (int 1F) */
|
||||
MEM_WW(0x1f << 2, 0xfa6e);
|
||||
|
||||
/* int 11 default location (Get Equipment Configuration) */
|
||||
MEM_WW(0x11 << 2, 0xf84d);
|
||||
/* int 12 default location (Get Conventional Memory Size) */
|
||||
MEM_WW(0x12 << 2, 0xf841);
|
||||
/* int 15 default location (I/O System Extensions) */
|
||||
MEM_WW(0x15 << 2, 0xf859);
|
||||
/* int 1A default location (RTC, PCI and others) */
|
||||
MEM_WW(0x1a << 2, 0xff6e);
|
||||
/* int 05 default location (Bound Exceeded) */
|
||||
MEM_WW(0x05 << 2, 0xff54);
|
||||
/* int 08 default location (Double Fault) */
|
||||
MEM_WW(0x08 << 2, 0xfea5);
|
||||
/* int 13 default location (Disk) */
|
||||
MEM_WW(0x13 << 2, 0xec59);
|
||||
/* int 0E default location (Page Fault) */
|
||||
MEM_WW(0x0e << 2, 0xef57);
|
||||
/* int 17 default location (Parallel Port) */
|
||||
MEM_WW(0x17 << 2, 0xefd2);
|
||||
/* fdd table default location (int 1e) */
|
||||
MEM_WW(0x1e << 2, 0xefc7);
|
||||
|
||||
/* Set Equipment flag to VGA */
|
||||
i = MEM_RB(0x0410) & 0xCF;
|
||||
MEM_WB(0x0410, i);
|
||||
/* XXX Perhaps setup more of the BDA here. See also int42(0x00). */
|
||||
}
|
||||
#endif
|
||||
|
||||
int setup_system_bios(void *base_addr)
|
||||
{
|
||||
char *base = (char *) base_addr;
|
||||
|
||||
/*
|
||||
* we trap the "industry standard entry points" to the BIOS
|
||||
* and all other locations by filling them with "hlt"
|
||||
* TODO: implement hlt-handler for these
|
||||
*/
|
||||
memset(base, 0xf4, 0x10000);
|
||||
|
||||
/* set bios date */
|
||||
strcpy(base + 0x0FFF5, "06/11/99");
|
||||
/* set up eisa ident string */
|
||||
strcpy(base + 0x0FFD9, "PCI_ISA");
|
||||
/* write system model id for IBM-AT */
|
||||
*((unsigned char *) (base + 0x0FFFE)) = 0xfc;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void reset_int_vect(void)
|
||||
{
|
||||
/*
|
||||
* This table is normally located at 0xF000:0xF0A4. However, int 0x42,
|
||||
* function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
|
||||
* 64kB. Note that because this data doesn't survive POST, int 0x42 should
|
||||
* only be used during EGA/VGA BIOS initialisation.
|
||||
*/
|
||||
static const u8 VideoParms[] = {
|
||||
/* Timing for modes 0x00 & 0x01 */
|
||||
0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
|
||||
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Timing for modes 0x02 & 0x03 */
|
||||
0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
|
||||
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Timing for modes 0x04, 0x05 & 0x06 */
|
||||
0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
|
||||
0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Timing for mode 0x07 */
|
||||
0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
|
||||
0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Display page lengths in little endian order */
|
||||
0x00, 0x08, /* Modes 0x00 and 0x01 */
|
||||
0x00, 0x10, /* Modes 0x02 and 0x03 */
|
||||
0x00, 0x40, /* Modes 0x04 and 0x05 */
|
||||
0x00, 0x40, /* Modes 0x06 and 0x07 */
|
||||
/* Number of columns for each mode */
|
||||
40, 40, 80, 80, 40, 40, 80, 80,
|
||||
/* CGA Mode register value for each mode */
|
||||
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
|
||||
/* Padding */
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(VideoParms); i++)
|
||||
MEM_WB(i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
|
||||
MEM_WW(0x1d << 2, 0x1000 - sizeof(VideoParms));
|
||||
MEM_WW((0x1d << 2) + 2, 0);
|
||||
|
||||
printf("SETUP INT\n");
|
||||
MEM_WW(0x10 << 2, 0xf065);
|
||||
MEM_WW((0x10 << 2) + 2, SYS_BIOS >> 4);
|
||||
MEM_WW(0x42 << 2, 0xf065);
|
||||
MEM_WW((0x42 << 2) + 2, SYS_BIOS >> 4);
|
||||
MEM_WW(0x6D << 2, 0xf065);
|
||||
MEM_WW((0x6D << 2) + 2, SYS_BIOS >> 4);
|
||||
}
|
||||
|
||||
void set_return_trap(void)
|
||||
{
|
||||
/*
|
||||
* Here we set the exit condition: We return when we encounter
|
||||
* 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory.
|
||||
*/
|
||||
MEM_WB(0x0600, 0xf4);
|
||||
|
||||
/*
|
||||
* Allocate a segment for the stack
|
||||
*/
|
||||
xf86Int10AllocPages(1, current->stackseg);
|
||||
}
|
||||
|
||||
void *xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex)
|
||||
{
|
||||
EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
|
||||
OptionInfoPtr options = NULL;
|
||||
|
||||
if (pEnt->device) {
|
||||
pointer configOptions = NULL;
|
||||
|
||||
/* Check if xf86CollectOptions() has already been called */
|
||||
if (((pEnt->index < 0) ||
|
||||
!xf86Screens[pEnt->index] ||
|
||||
!(configOptions = xf86Screens[pEnt->index]->options)) &&
|
||||
pEnt->device)
|
||||
configOptions = pEnt->device->options;
|
||||
|
||||
if (configOptions) {
|
||||
if (!(options = (OptionInfoPtr) xalloc(sizeof(INT10Options))))
|
||||
return NULL;
|
||||
|
||||
(void) memcpy(options, INT10Options, sizeof(INT10Options));
|
||||
xf86ProcessOptions(pScrn->scrnIndex, configOptions, options);
|
||||
}
|
||||
}
|
||||
xfree(pEnt);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Bool int10skip(void *options)
|
||||
{
|
||||
Bool noint10 = FALSE;
|
||||
|
||||
if (!options)
|
||||
return FALSE;
|
||||
|
||||
xf86GetOptValBool(options, OPT_NOINT10, &noint10);
|
||||
return noint10;
|
||||
}
|
||||
|
||||
Bool int10_check_bios(int scrnIndex, int codeSeg, unsigned char *vbiosMem)
|
||||
{
|
||||
int size;
|
||||
|
||||
if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */
|
||||
((codeSeg << 4) < V_BIOS) || ((codeSeg << 4) >= SYS_SIZE))
|
||||
return FALSE;
|
||||
|
||||
if (xf86IsPc98())
|
||||
return FALSE;
|
||||
|
||||
if ((*vbiosMem != 0x55) || (*(vbiosMem + 1) != 0xAA) || !*(vbiosMem + 2))
|
||||
return FALSE;
|
||||
|
||||
size = *(vbiosMem + 2) * 512;
|
||||
|
||||
if ((size + (codeSeg << 4)) > SYS_SIZE)
|
||||
return FALSE;
|
||||
|
||||
if (bios_checksum(vbiosMem, size))
|
||||
xf86DrvMsg(scrnIndex, X_WARNING, "Bad V_BIOS checksum\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool initPrimary(void *options)
|
||||
{
|
||||
Bool initPrimary = FALSE;
|
||||
|
||||
if (!options)
|
||||
return FALSE;
|
||||
|
||||
xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary);
|
||||
return initPrimary;
|
||||
}
|
||||
|
||||
void xf86int10ParseBiosLocation(void *options, xf86int10BiosLocationPtr bios)
|
||||
{
|
||||
char *s;
|
||||
char *p;
|
||||
char *str = NULL;
|
||||
|
||||
if (options)
|
||||
str = xf86GetOptValString(options, OPT_BIOS_LOCATION);
|
||||
|
||||
bios->bus = BUS_NONE;
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
s = xstrdup(str);
|
||||
p = strtok(s, ":");
|
||||
if (xf86NameCmp(p, "pci"))
|
||||
bios->bus = BUS_PCI;
|
||||
else if (xf86NameCmp(p, "primary"))
|
||||
bios->bus = BUS_ISA;
|
||||
|
||||
xfree(s);
|
||||
|
||||
if (bios->bus == BUS_NONE)
|
||||
return;
|
||||
|
||||
s = xstrdup(str);
|
||||
p = strchr(s, ':');
|
||||
|
||||
switch (bios->bus) {
|
||||
case BUS_ISA:
|
||||
if (p)
|
||||
bios->location.legacy = atoi(++p);
|
||||
else
|
||||
bios->location.legacy = 0;
|
||||
break;
|
||||
case BUS_PCI:
|
||||
if (p) {
|
||||
bios->location.pci.bus = atoi(++p);
|
||||
if ((p = strchr(p, ':'))) {
|
||||
bios->location.pci.dev = atoi(++p);
|
||||
if ((p = strchr(p, ':'))) {
|
||||
bios->location.pci.func = atoi(++p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
bios->bus = BUS_NONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xfree(s);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,478 @@
|
|||
#include <stdio.h>
|
||||
#include "test.h"
|
||||
#include "pci.h"
|
||||
|
||||
void x86emu_dump_xregs(void);
|
||||
extern ptr current;
|
||||
extern int verbose;
|
||||
|
||||
|
||||
#ifndef _PC
|
||||
/*
|
||||
* This is derived from a number of PC system BIOS'es. The intent here is to
|
||||
* provide very primitive video support, before an EGA/VGA BIOS installs its
|
||||
* own interrupt vector. Here, "Ignored" calls should remain so. "Not
|
||||
* Implemented" denotes functionality that can be implemented should the need
|
||||
* arise. What are "Not Implemented" throughout are video memory accesses.
|
||||
* Also, very little input validity checking is done here.
|
||||
*/
|
||||
int int42_handler()
|
||||
{
|
||||
|
||||
if (verbose && X86_AH != 0x0e) {
|
||||
printf("int%x\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
}
|
||||
|
||||
switch (X86_AH) {
|
||||
case 0x00:
|
||||
/* Set Video Mode */
|
||||
/* Enter: AL = video mode number */
|
||||
/* Leave: Nothing */
|
||||
/* Implemented (except for clearing the screen) */
|
||||
{ /* Localise */
|
||||
int i;
|
||||
u16 ioport, int1d, regvals, tmp;
|
||||
u8 mode, cgamode, cgacolour;
|
||||
|
||||
/*
|
||||
* Ignore all mode numbers but 0x00-0x13. Some systems also ignore
|
||||
* 0x0B and 0x0C, but don't do that here.
|
||||
*/
|
||||
if (X86_AL > 0x13)
|
||||
break;
|
||||
|
||||
/*
|
||||
* You didn't think that was really the mode set, did you? There
|
||||
* are only so many slots in the video parameter table...
|
||||
*/
|
||||
mode = X86_AL;
|
||||
ioport = 0x03D4;
|
||||
switch (MEM_RB(0x0410) & 0x30) {
|
||||
case 0x30: /* MDA */
|
||||
mode = 0x07; /* Force mode to 0x07 */
|
||||
ioport = 0x03B4;
|
||||
break;
|
||||
case 0x10: /* CGA 40x25 */
|
||||
if (mode >= 0x07)
|
||||
mode = 0x01;
|
||||
break;
|
||||
case 0x20: /* CGA 80x25 (MCGA?) */
|
||||
if (mode >= 0x07)
|
||||
mode = 0x03;
|
||||
break;
|
||||
case 0x00: /* EGA/VGA */
|
||||
if (mode >= 0x07) /* Don't try MDA timings */
|
||||
mode = 0x01; /* !?!?! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Locate data in video parameter table */
|
||||
int1d = MEM_RW(0x1d << 2);
|
||||
regvals = ((mode >> 1) << 4) + int1d;
|
||||
cgacolour = 0x30;
|
||||
if (mode == 0x06) {
|
||||
regvals -= 0x10;
|
||||
cgacolour = 0x3F;
|
||||
}
|
||||
|
||||
/** Update BIOS Data Area **/
|
||||
|
||||
/* Video mode */
|
||||
MEM_WB(0x0449, mode);
|
||||
|
||||
/* Columns */
|
||||
tmp = MEM_RB(mode + int1d + 0x48);
|
||||
MEM_WW(0x044A, tmp);
|
||||
|
||||
/* Page length */
|
||||
tmp = MEM_RW((mode & 0x06) + int1d + 0x40);
|
||||
MEM_WW(0x044C, tmp);
|
||||
|
||||
/* Start Address */
|
||||
MEM_WW(0x044E, 0);
|
||||
|
||||
/* Cursor positions, one for each display page */
|
||||
for (i = 0x0450; i < 0x0460; i += 2)
|
||||
MEM_WW(i, 0);
|
||||
|
||||
/* Cursor start & end scanlines */
|
||||
tmp = MEM_RB(regvals + 0x0B);
|
||||
MEM_WB(0x0460, tmp);
|
||||
tmp = MEM_RB(regvals + 0x0A);
|
||||
MEM_WB(0x0461, tmp);
|
||||
|
||||
/* Current display page number */
|
||||
MEM_WB(0x0462, 0);
|
||||
|
||||
/* CRTC I/O address */
|
||||
MEM_WW(0x0463, ioport);
|
||||
|
||||
/* CGA Mode register value */
|
||||
cgamode = MEM_RB(mode + int1d + 0x50);
|
||||
MEM_WB(0x0465, cgamode);
|
||||
|
||||
/* CGA Colour register value */
|
||||
MEM_WB(0x0466, cgacolour);
|
||||
|
||||
/* Rows */
|
||||
MEM_WB(0x0484, (25 - 1));
|
||||
|
||||
/* Programme the mode */
|
||||
outb(ioport + 4, cgamode & 0x37); /* Turn off screen */
|
||||
for (i = 0; i < 0x10; i++) {
|
||||
tmp = MEM_RB(regvals + i);
|
||||
outb(ioport, i);
|
||||
outb(ioport + 1, tmp);
|
||||
}
|
||||
outb(ioport + 5, cgacolour); /* Select colour mode */
|
||||
outb(ioport + 4, cgamode); /* Turn on screen */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
/* Set Cursor Type */
|
||||
/* Enter: CH = starting line for cursor */
|
||||
/* CL = ending line for cursor */
|
||||
/* Leave: Nothing */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
u16 ioport = MEM_RW(0x0463);
|
||||
|
||||
MEM_WB(0x0460, X86_CL);
|
||||
MEM_WB(0x0461, X86_CH);
|
||||
|
||||
outb(ioport, 0x0A);
|
||||
outb(ioport + 1, X86_CH);
|
||||
outb(ioport, 0x0B);
|
||||
outb(ioport + 1, X86_CL);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
/* Set Cursor Position */
|
||||
/* Enter: BH = display page number */
|
||||
/* DH = row */
|
||||
/* DL = column */
|
||||
/* Leave: Nothing */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
u16 offset, ioport;
|
||||
|
||||
MEM_WB((X86_BH << 1) + 0x0450, X86_DL);
|
||||
MEM_WB((X86_BH << 1) + 0x0451, X86_DH);
|
||||
|
||||
if (X86_BH != MEM_RB(0x0462))
|
||||
break;
|
||||
|
||||
offset = (X86_DH * MEM_RW(0x044A)) + X86_DL;
|
||||
offset += MEM_RW(0x044E) << 1;
|
||||
|
||||
ioport = MEM_RW(0x0463);
|
||||
outb(ioport, 0x0E);
|
||||
outb(ioport + 1, offset >> 8);
|
||||
outb(ioport, 0x0F);
|
||||
outb(ioport + 1, offset & 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
/* Get Cursor Position */
|
||||
/* Enter: BH = display page number */
|
||||
/* Leave: CH = starting line for cursor */
|
||||
/* CL = ending line for cursor */
|
||||
/* DH = row */
|
||||
/* DL = column */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
X86_CL = MEM_RB(0x0460);
|
||||
X86_CH = MEM_RB(0x0461);
|
||||
X86_DL = MEM_RB((X86_BH << 1) + 0x0450);
|
||||
X86_DH = MEM_RB((X86_BH << 1) + 0x0451);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
/* Get Light Pen Position */
|
||||
/* Enter: Nothing */
|
||||
/* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */
|
||||
/* BX = pixel column */
|
||||
/* CX = pixel row */
|
||||
/* DH = character row */
|
||||
/* DL = character column */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x - Get Light Pen Position. "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
X86_AH = X86_BX = X86_CX = X86_DX = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
/* Set Display Page */
|
||||
/* Enter: AL = display page number */
|
||||
/* Leave: Nothing */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
u16 start, ioport = MEM_RW(0x0463);
|
||||
u8 x, y;
|
||||
|
||||
/* Calculate new start address */
|
||||
MEM_WB(0x0462, X86_AL);
|
||||
start = X86_AL * MEM_RW(0x044C);
|
||||
MEM_WW(0x044E, start);
|
||||
start <<= 1;
|
||||
|
||||
/* Update start address */
|
||||
outb(ioport, 0x0C);
|
||||
outb(ioport + 1, start >> 8);
|
||||
outb(ioport, 0x0D);
|
||||
outb(ioport + 1, start & 0xFF);
|
||||
|
||||
/* Switch cursor position */
|
||||
y = MEM_RB((X86_AL << 1) + 0x0450);
|
||||
x = MEM_RB((X86_AL << 1) + 0x0451);
|
||||
start += (y * MEM_RW(0x044A)) + x;
|
||||
|
||||
/* Update cursor position */
|
||||
outb(ioport, 0x0E);
|
||||
outb(ioport + 1, start >> 8);
|
||||
outb(ioport, 0x0F);
|
||||
outb(ioport + 1, start & 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
/* Initialise or Scroll Window Up */
|
||||
/* Enter: AL = lines to scroll up */
|
||||
/* BH = attribute for blank */
|
||||
/* CH = upper y of window */
|
||||
/* CL = left x of window */
|
||||
/* DH = lower y of window */
|
||||
/* DL = right x of window */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x: Initialise or Scroll Window Up - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
/* Initialise or Scroll Window Down */
|
||||
/* Enter: AL = lines to scroll down */
|
||||
/* BH = attribute for blank */
|
||||
/* CH = upper y of window */
|
||||
/* CL = left x of window */
|
||||
/* DH = lower y of window */
|
||||
/* DL = right x of window */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x: Initialise or Scroll Window Down - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
/* Read Character and Attribute at Cursor */
|
||||
/* Enter: BH = display page number */
|
||||
/* Leave: AH = attribute */
|
||||
/* AL = character */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf
|
||||
("int%x: Read Character and Attribute at Cursor - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
X86_AX = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
/* Write Character and Attribute at Cursor */
|
||||
/* Enter: AL = character */
|
||||
/* BH = display page number */
|
||||
/* BL = attribute (text) or colour (graphics) */
|
||||
/* CX = replication count */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf
|
||||
("int%x: Write Character and Attribute at Cursor - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
/* Write Character at Cursor */
|
||||
/* Enter: AL = character */
|
||||
/* BH = display page number */
|
||||
/* BL = colour */
|
||||
/* CX = replication count */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x: Write Character at Cursor - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0b:
|
||||
/* Set Palette, Background or Border */
|
||||
/* Enter: BH = 0x00 or 0x01 */
|
||||
/* BL = colour or palette (respectively) */
|
||||
/* Leave: Nothing */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
u16 ioport = MEM_RW(0x0463) + 5;
|
||||
u8 cgacolour = MEM_RB(0x0466);
|
||||
|
||||
if (X86_BH) {
|
||||
cgacolour &= 0xDF;
|
||||
cgacolour |= (X86_BL & 0x01) << 5;
|
||||
} else {
|
||||
cgacolour &= 0xE0;
|
||||
cgacolour |= X86_BL & 0x1F;
|
||||
}
|
||||
|
||||
MEM_WB(0x0466, cgacolour);
|
||||
outb(ioport, cgacolour);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0c:
|
||||
/* Write Graphics Pixel */
|
||||
/* Enter: AL = pixel value */
|
||||
/* BH = display page number */
|
||||
/* CX = column */
|
||||
/* DX = row */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x: Write Graphics Pixel - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0d:
|
||||
/* Read Graphics Pixel */
|
||||
/* Enter: BH = display page number */
|
||||
/* CX = column */
|
||||
/* DX = row */
|
||||
/* Leave: AL = pixel value */
|
||||
/* Not Implemented */
|
||||
{ /* Localise */
|
||||
printf("int%x: Write Graphics Pixel - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
X86_AL = 0;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0e:
|
||||
/* Write Character in Teletype Mode */
|
||||
/* Enter: AL = character */
|
||||
/* BH = display page number */
|
||||
/* BL = foreground colour */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
/* WARNING: Emulation of BEL characters will require */
|
||||
/* emulation of RTC and PC speaker I/O. */
|
||||
/* Also, this recurses through int 0x10 */
|
||||
/* which might or might not have been */
|
||||
/* installed yet. */
|
||||
{ /* Localise */
|
||||
#ifdef PARANOID
|
||||
printf("int%x: Write Character in Teletype Mode - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
#endif
|
||||
printf("%c", X86_AL);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
/* Get Video Mode */
|
||||
/* Enter: Nothing */
|
||||
/* Leave: AH = number of columns */
|
||||
/* AL = video mode number */
|
||||
/* BH = display page number */
|
||||
/* Implemented */
|
||||
{ /* Localise */
|
||||
X86_AH = MEM_RW(0x044A);
|
||||
X86_AL = MEM_RB(0x0449);
|
||||
X86_BH = MEM_RB(0x0462);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
/* Colour Control (subfunction in AL) */
|
||||
/* Enter: Various */
|
||||
/* Leave: Various */
|
||||
/* Ignored */
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
/* Font Control (subfunction in AL) */
|
||||
/* Enter: Various */
|
||||
/* Leave: Various */
|
||||
/* Ignored */
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
/* Miscellaneous (subfunction in BL) */
|
||||
/* Enter: Various */
|
||||
/* Leave: Various */
|
||||
/* Ignored. Previous code here optionally allowed */
|
||||
/* the enabling and disabling of VGA, but no system */
|
||||
/* BIOS I've come across actually implements it. */
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
/* Write String in Teletype Mode */
|
||||
/* Enter: AL = write mode */
|
||||
/* BL = attribute (if (AL & 0x02) == 0) */
|
||||
/* CX = string length */
|
||||
/* DH = row */
|
||||
/* DL = column */
|
||||
/* ES:BP = string segment:offset */
|
||||
/* Leave: Nothing */
|
||||
/* Not Implemented */
|
||||
/* WARNING: Emulation of BEL characters will require */
|
||||
/* emulation of RTC and PC speaker I/O. */
|
||||
/* Also, this recurses through int 0x10 */
|
||||
/* which might or might not have been */
|
||||
/* installed yet. */
|
||||
{ /* Localise */
|
||||
printf("int%x: Write String in Teletype Mode - "
|
||||
"Function not implemented.\n", current->num);
|
||||
x86emu_dump_xregs();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Various extensions */
|
||||
/* Enter: Various */
|
||||
/* Leave: Various */
|
||||
/* Ignored */
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#include <stdio.h>
|
||||
#include "test.h"
|
||||
|
||||
void x86emu_dump_xregs();
|
||||
|
||||
int int15_handler(void)
|
||||
{
|
||||
printf("\nint15 encountered.\n");
|
||||
x86emu_dump_xregs();
|
||||
X86_EAX = 0;
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int int16_handler(void)
|
||||
{
|
||||
printf("\nint16: keyboard not supported right now.\n");
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
#include <stdio.h>
|
||||
#include "test.h"
|
||||
#include "pci-userspace.h"
|
||||
|
||||
#define DEBUG_INT1A
|
||||
|
||||
#define SUCCESSFUL 0x00
|
||||
#define DEVICE_NOT_FOUND 0x86
|
||||
#define BAD_REGISTER_NUMBER 0x87
|
||||
|
||||
void x86emu_dump_xregs(void);
|
||||
extern int verbose;
|
||||
|
||||
|
||||
int int1A_handler()
|
||||
{
|
||||
PCITAG tag;
|
||||
pciVideoPtr pvp = NULL;
|
||||
|
||||
if (verbose) {
|
||||
printf("\nint1a encountered.\n");
|
||||
x86emu_dump_xregs();
|
||||
}
|
||||
|
||||
switch (X86_AX) {
|
||||
case 0xb101:
|
||||
X86_EAX = 0x00; /* no config space/special cycle support */
|
||||
X86_AL = 0x01; /* config mechanism 1 */
|
||||
X86_EDX = 0x20494350; /* " ICP" */
|
||||
X86_EBX = 0x0210; /* Version 2.10 */
|
||||
X86_ECX &= 0xFF00;
|
||||
X86_ECX |= (pciNumBuses & 0xFF); /* Max bus number in system */
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
#ifdef DEBUG_INT1A
|
||||
if (verbose)
|
||||
printf("PCI bios present.\n");
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb102:
|
||||
if (X86_DX == pvp->vendor_id && X86_CX == pvp->device_id && X86_ESI == 0) {
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
X86_EBX = pciSlotBX(pvp);
|
||||
}
|
||||
#ifdef SHOW_ALL_DEVICES
|
||||
else if ((pvp = xf86FindPciDeviceVendor(X86_EDX, X86_ECX, X86_ESI, pvp))) {
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
X86_EBX = pciSlotBX(pvp);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x ebx=0x%x eflags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb103:
|
||||
#if 0
|
||||
if (X86_CL == pvp->interface &&
|
||||
X86_CH == pvp->subclass &&
|
||||
((X86_ECX & 0xFFFF0000) >> 16) == pvp->class) {
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EBX = pciSlotBX(pvp);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
}
|
||||
#else
|
||||
/* FIXME: dirty hack */
|
||||
if (0);
|
||||
#endif
|
||||
#ifdef SHOW_ALL_DEVICES
|
||||
else if ((pvp = FindPciClass(X86_CL, X86_CH,
|
||||
(X86_ECX & 0xffff0000) >> 16,
|
||||
X86_ESI, pvp))) {
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
X86_EBX = pciSlotBX(pvp);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb108:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
X86_CL = pciReadByte(tag, X86_EDI);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb109:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
X86_CX = pciReadWord(tag, X86_EDI);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb10a:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
X86_ECX = pciReadLong(tag, X86_EDI);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb10b:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
pciWriteByte(tag, X86_EDI, X86_CL);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb10c:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
pciWriteWord(tag, X86_EDI, X86_CX);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
case 0xb10d:
|
||||
if ((tag = findPci(X86_EBX))) {
|
||||
pciWriteLong(tag, X86_EDI, X86_ECX);
|
||||
X86_EAX = X86_AL | (SUCCESSFUL << 8);
|
||||
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
|
||||
} else {
|
||||
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
|
||||
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
|
||||
}
|
||||
#ifdef DEBUG_INT1A
|
||||
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
|
||||
#endif
|
||||
return 1;
|
||||
default:
|
||||
printf("int1a: subfunction not implemented.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int intE6_handler()
|
||||
{
|
||||
#if 0
|
||||
pciVideoPtr pvp;
|
||||
|
||||
if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex)))
|
||||
X86_AX = (pvp->bus << 8) | (pvp->device << 3) | (pvp->func & 0x7);
|
||||
pushw(X86_CS);
|
||||
pushw(X86_IP);
|
||||
X86_CS = pInt->BIOSseg;
|
||||
X86_EIP = 0x0003;
|
||||
X86_ES = 0; /* standard pc es */
|
||||
#endif
|
||||
printf("intE6 not supported right now.\n");
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
#include <stdio.h>
|
||||
#include <pci/pci.h>
|
||||
#include "pci.h"
|
||||
|
||||
#define PCITAG struct pci_filter *
|
||||
|
||||
#define DEBUG_PCI 1
|
||||
|
||||
struct pci_access *pacc;
|
||||
struct pci_dev *dev;
|
||||
|
||||
struct pci_filter ltag;
|
||||
|
||||
|
||||
int pciNumBuses = 0;
|
||||
|
||||
int pciInit(void)
|
||||
{
|
||||
pacc = pci_alloc();
|
||||
|
||||
pci_init(pacc);
|
||||
pci_scan_bus(pacc);
|
||||
for (dev = pacc->devices; dev; dev = dev->next) {
|
||||
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pciExit(void)
|
||||
{
|
||||
pci_cleanup(pacc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCITAG findPci(unsigned short bx)
|
||||
{
|
||||
PCITAG tag = <ag;
|
||||
|
||||
int bus = (bx >> 8) & 0xFF;
|
||||
int slot = (bx >> 3) & 0x1F;
|
||||
int func = bx & 0x7;
|
||||
|
||||
tag->bus = bus;
|
||||
tag->slot = slot;
|
||||
tag->func = func;
|
||||
|
||||
if (pci_get_dev(pacc, bus, slot, func))
|
||||
return tag;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 pciSlotBX(PCITAG tag)
|
||||
{
|
||||
return (tag->bus << 8) | (tag->slot << 3) | (tag->func);
|
||||
}
|
||||
|
||||
u8 pciReadByte(PCITAG tag, u32 idx)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
return pci_read_byte(d, idx);
|
||||
#ifdef DEBUG_PCI
|
||||
printf("PCI: device not found while read byte (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 pciReadWord(PCITAG tag, u32 idx)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
return pci_read_word(d, idx);
|
||||
#ifdef DEBUG_PCI
|
||||
printf("PCI: device not found while read word (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 pciReadLong(PCITAG tag, u32 idx)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
return pci_read_long(d, idx);
|
||||
#ifdef DEBUG_PCI
|
||||
printf("PCI: device not found while read long (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void pciWriteLong(PCITAG tag, u32 idx, u32 data)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
pci_write_long(d, idx, data);
|
||||
#ifdef DEBUG_PCI
|
||||
else
|
||||
printf("PCI: device not found while write long (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pciWriteWord(PCITAG tag, u32 idx, u16 data)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
pci_write_word(d, idx, data);
|
||||
#ifdef DEBUG_PCI
|
||||
else
|
||||
printf("PCI: device not found while write word (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void pciWriteByte(PCITAG tag, u32 idx, u8 data)
|
||||
{
|
||||
struct pci_dev *d;
|
||||
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
|
||||
pci_write_long(d, idx, data);
|
||||
#ifdef DEBUG_PCI
|
||||
else
|
||||
printf("PCI: device not found while write long (%x:%x.%x)\n",
|
||||
tag->bus, tag->slot, tag->func);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#include "pci.h"
|
||||
|
||||
typedef unsigned long pciaddr_t;
|
||||
typedef u8 byte;
|
||||
typedef u16 word;
|
||||
|
||||
struct pci_dev {
|
||||
struct pci_dev *next; /* Next device in the chain */
|
||||
word bus; /* Higher byte can select host bridges */
|
||||
byte dev, func; /* Device and function */
|
||||
|
||||
/* These fields are set by pci_fill_info() */
|
||||
int known_fields; /* Set of info fields already known */
|
||||
word vendor_id, device_id; /* Identity of the device */
|
||||
int irq; /* IRQ number */
|
||||
pciaddr_t base_addr[6]; /* Base addresses */
|
||||
pciaddr_t size[6]; /* Region sizes */
|
||||
pciaddr_t rom_base_addr; /* Expansion ROM base address */
|
||||
pciaddr_t rom_size; /* Expansion ROM size */
|
||||
|
||||
/* Fields used internally: */
|
||||
void *access;
|
||||
void *methods;
|
||||
byte *cache; /* Cached information */
|
||||
int cache_len;
|
||||
int hdrtype; /* Direct methods: header type */
|
||||
void *aux; /* Auxillary data */
|
||||
};
|
||||
|
||||
|
||||
struct pci_filter {
|
||||
int bus, slot, func; /* -1 = ANY */
|
||||
int vendor, device;
|
||||
};
|
||||
|
||||
|
||||
#define PCITAG struct pci_filter *
|
||||
#define pciVideoPtr struct pci_dev *
|
||||
|
||||
extern int pciNumBuses;
|
||||
|
||||
int pciInit(void);
|
||||
int pciExit(void);
|
||||
|
||||
|
||||
PCITAG findPci(unsigned short bx);
|
||||
u32 pciSlotBX(pciVideoPtr pvp);
|
||||
|
||||
void pciWriteLong(PCITAG tag, u32 idx, u32 data);
|
||||
void pciWriteWord(PCITAG tag, u32 idx, u16 data);
|
||||
void pciWriteByte(PCITAG tag, u32 idx, u8 data);
|
||||
|
||||
u32 pciReadLong(PCITAG tag, u32 idx);
|
||||
u16 pciReadWord(PCITAG tag, u32 idx);
|
||||
u8 pciReadByte(PCITAG tag, u32 idx);
|
|
@ -0,0 +1,2 @@
|
|||
void x_outb(u16 port, u8 val);
|
||||
#define outb x_outb
|
|
@ -0,0 +1,89 @@
|
|||
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86x86emu.h,v 1.2 2001/01/06 20:19:13 tsi Exp $ */
|
||||
/*
|
||||
* XFree86 int10 module
|
||||
* execute BIOS int 10h calls in x86 real mode environment
|
||||
* Copyright 1999 Egbert Eich
|
||||
*/
|
||||
#ifndef XF86X86EMU_H_
|
||||
#define XF86X86EMU_H_
|
||||
#include <x86emu.h>
|
||||
|
||||
#define M _X86EMU_env
|
||||
|
||||
#define X86_EAX M.x86.R_EAX
|
||||
#define X86_EBX M.x86.R_EBX
|
||||
#define X86_ECX M.x86.R_ECX
|
||||
#define X86_EDX M.x86.R_EDX
|
||||
#define X86_ESI M.x86.R_ESI
|
||||
#define X86_EDI M.x86.R_EDI
|
||||
#define X86_EBP M.x86.R_EBP
|
||||
#define X86_EIP M.x86.R_EIP
|
||||
#define X86_ESP M.x86.R_ESP
|
||||
#define X86_EFLAGS M.x86.R_EFLG
|
||||
|
||||
#define X86_FLAGS M.x86.R_FLG
|
||||
#define X86_AX M.x86.R_AX
|
||||
#define X86_BX M.x86.R_BX
|
||||
#define X86_CX M.x86.R_CX
|
||||
#define X86_DX M.x86.R_DX
|
||||
#define X86_SI M.x86.R_SI
|
||||
#define X86_DI M.x86.R_DI
|
||||
#define X86_BP M.x86.R_BP
|
||||
#define X86_IP M.x86.R_IP
|
||||
#define X86_SP M.x86.R_SP
|
||||
#define X86_CS M.x86.R_CS
|
||||
#define X86_DS M.x86.R_DS
|
||||
#define X86_ES M.x86.R_ES
|
||||
#define X86_SS M.x86.R_SS
|
||||
#define X86_FS M.x86.R_FS
|
||||
#define X86_GS M.x86.R_GS
|
||||
|
||||
#define X86_AL M.x86.R_AL
|
||||
#define X86_BL M.x86.R_BL
|
||||
#define X86_CL M.x86.R_CL
|
||||
#define X86_DL M.x86.R_DL
|
||||
|
||||
#define X86_AH M.x86.R_AH
|
||||
#define X86_BH M.x86.R_BH
|
||||
#define X86_CH M.x86.R_CH
|
||||
#define X86_DH M.x86.R_DH
|
||||
|
||||
|
||||
/* int10 info structure */
|
||||
typedef struct {
|
||||
u16 BIOSseg;
|
||||
u16 inb40time;
|
||||
struct _mem *mem;
|
||||
int num;
|
||||
int ax;
|
||||
int bx;
|
||||
int cx;
|
||||
int dx;
|
||||
int si;
|
||||
int di;
|
||||
int es;
|
||||
int bp;
|
||||
int flags;
|
||||
int stackseg;
|
||||
} _ptr, *ptr;
|
||||
|
||||
typedef struct _mem {
|
||||
u8(*rb) (ptr, int);
|
||||
u16(*rw) (ptr, int);
|
||||
u32(*rl) (ptr, int);
|
||||
void (*wb) (ptr, int, u8);
|
||||
void (*ww) (ptr, int, u16);
|
||||
void (*wl) (ptr, int, u32);
|
||||
} mem;
|
||||
|
||||
#define MEM_WB(where, what) wrb(where,what)
|
||||
#define MEM_WW(where, what) wrw(where, what)
|
||||
#define MEM_WL(where, what) wrl(where, what)
|
||||
|
||||
#define MEM_RB(where) rdb(where)
|
||||
#define MEM_RW(where) rdw(where)
|
||||
#define MEM_RL(where) rdl(where)
|
||||
|
||||
extern ptr current;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,328 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/io.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define die(x) { perror(x); exit(1); }
|
||||
|
||||
#include <x86emu.h>
|
||||
#include "test.h"
|
||||
#include "pci-userspace.h"
|
||||
|
||||
void x86emu_dump_xregs(void);
|
||||
int int15_handler(void);
|
||||
int int16_handler(void);
|
||||
int int1A_handler(void);
|
||||
#ifndef _PC
|
||||
int int42_handler(void);
|
||||
#endif
|
||||
int intE6_handler(void);
|
||||
|
||||
void pushw(u16 val);
|
||||
|
||||
extern int teststart, testend;
|
||||
|
||||
_ptr p;
|
||||
ptr current = 0;
|
||||
unsigned char biosmem[1024 * 1024];
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
|
||||
/* Interrupt multiplexer */
|
||||
|
||||
void do_int(int num)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printf("int%x vector at %x\n", num, getIntVect(num));
|
||||
|
||||
/* This is a pInt leftover */
|
||||
current->num = num;
|
||||
|
||||
switch (num) {
|
||||
#ifndef _PC
|
||||
case 0x10:
|
||||
case 0x42:
|
||||
case 0x6D:
|
||||
|
||||
if (getIntVect(num) == 0xFF065) {
|
||||
ret = int42_handler();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 0x15:
|
||||
ret = int15_handler();
|
||||
break;
|
||||
case 0x16:
|
||||
ret = int16_handler();
|
||||
break;
|
||||
case 0x1A:
|
||||
ret = int1A_handler();
|
||||
break;
|
||||
case 0xe6:
|
||||
ret = intE6_handler();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = run_bios_int(num);
|
||||
|
||||
if (!ret) {
|
||||
printf("\nint%x: not implemented\n", num);
|
||||
x86emu_dump_xregs();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *mapitin(char *file, off_t where, size_t size)
|
||||
{
|
||||
void *z;
|
||||
|
||||
int fd = open(file, O_RDWR, 0);
|
||||
|
||||
if (fd < 0)
|
||||
die(file);
|
||||
z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
|
||||
if (z == (void *) -1)
|
||||
die("mmap");
|
||||
close(fd);
|
||||
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
u8 x_inb(u16 port);
|
||||
u16 x_inw(u16 port);
|
||||
void x_outb(u16 port, u8 val);
|
||||
void x_outw(u16 port, u16 val);
|
||||
u32 x_inl(u16 port);
|
||||
void x_outl(u16 port, u32 val);
|
||||
|
||||
|
||||
X86EMU_pioFuncs myfuncs = {
|
||||
x_inb, x_inw, x_inl,
|
||||
x_outb, x_outw, x_outl
|
||||
};
|
||||
|
||||
|
||||
void usage(char *name)
|
||||
{
|
||||
printf
|
||||
("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
|
||||
name);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *absegname = 0;
|
||||
void *abseg = 0;
|
||||
int i, c, trace = 0;
|
||||
unsigned char *cp;
|
||||
char *filename;
|
||||
size_t size = 0;
|
||||
int base = 0;
|
||||
int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
|
||||
int parse_rom = 0;
|
||||
char *fsegname = 0;
|
||||
unsigned char *fsegptr;
|
||||
unsigned short initialip = 0, initialcs = 0, devfn = 0;
|
||||
X86EMU_intrFuncs intFuncs[256];
|
||||
void X86EMU_setMemBase(void *base, size_t size);
|
||||
void X86EMU_setabseg(void *abseg);
|
||||
void x86emu_dump_xregs(void);
|
||||
int X86EMU_set_debug(int debug);
|
||||
int debugflag = 0;
|
||||
|
||||
const char *optstring = "vh?b:i:c:s:tpd:";
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"trace", 0, 0, 't'},
|
||||
{"base", 1, 0, 'b'},
|
||||
{"fseg", 1, 0, 'f'},
|
||||
{"instructionpointer", 1, 0, 'i'},
|
||||
{"codesegment", 1, 0, 'c'},
|
||||
{"absegment", 1, 0, 'a'},
|
||||
{"size", 1, 0, 's'},
|
||||
{"parserom", 0, 0, 'p'},
|
||||
{"device", 1, 0, 'd'},
|
||||
{"debug", 1, 0, 'D'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, optstring, long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 't':
|
||||
trace = 1;
|
||||
break;
|
||||
case 'b':
|
||||
base = strtol(optarg, 0, 0);
|
||||
have_base = 1;
|
||||
break;
|
||||
case 'i':
|
||||
initialip = strtol(optarg, 0, 0);
|
||||
have_ip = 1;
|
||||
break;
|
||||
case 'c':
|
||||
initialcs = strtol(optarg, 0, 0);
|
||||
have_cs = 1;
|
||||
break;
|
||||
case 's':
|
||||
size = strtol(optarg, 0, 0);
|
||||
have_size = 1;
|
||||
break;
|
||||
case 'p':
|
||||
printf("Parsing rom images not implemented.\n");
|
||||
parse_rom = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fsegname = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
absegname = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
devfn = strtol(optarg, 0, 0);
|
||||
break;
|
||||
case 'D':
|
||||
debugflag = strtol(optarg, 0, 0);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown option \n");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
printf("Filename missing.\n");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (optind < argc) {
|
||||
printf("running file %s\n", argv[optind]);
|
||||
filename = argv[optind];
|
||||
optind++;
|
||||
/* normally we would do continue, but for
|
||||
* now only one filename is supported.
|
||||
*/
|
||||
/* continue; */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_size) {
|
||||
printf("No size specified. defaulting to 32k\n");
|
||||
size = 32 * 1024;
|
||||
}
|
||||
if (!have_base) {
|
||||
printf("No base specified. defaulting to 0xc0000\n");
|
||||
base = 0xc0000;
|
||||
}
|
||||
if (!have_cs) {
|
||||
printf("No initial code segment specified. defaulting to 0xc000\n");
|
||||
initialcs = 0xc000;
|
||||
}
|
||||
if (!have_ip) {
|
||||
printf
|
||||
("No initial instruction pointer specified. defaulting to 0x0003\n");
|
||||
initialip = 0x0003;
|
||||
}
|
||||
|
||||
//printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
|
||||
|
||||
if (absegname) {
|
||||
abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
|
||||
if (!abseg)
|
||||
die(absegname);
|
||||
}
|
||||
|
||||
current = &p;
|
||||
X86EMU_setMemBase(biosmem, sizeof(biosmem));
|
||||
X86EMU_setabseg(abseg);
|
||||
X86EMU_setupPioFuncs(&myfuncs);
|
||||
ioperm(0, 0x400, 1);
|
||||
|
||||
if (iopl(3) < 0)
|
||||
die("iopl");
|
||||
|
||||
/* Emergency sync ;-) */
|
||||
sync();
|
||||
sync();
|
||||
|
||||
/* Setting up interrupt environment.
|
||||
* basically this means initializing PCI and
|
||||
* intXX handlers.
|
||||
*/
|
||||
pciInit();
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intFuncs[i] = do_int;
|
||||
X86EMU_setupIntrFuncs(intFuncs);
|
||||
cp = mapitin(filename, (off_t) 0, size);
|
||||
|
||||
current->ax = devfn ? devfn : 0xff;
|
||||
current->dx = 0x80;
|
||||
// current->ip = 0;
|
||||
for (i = 0; i < size; i++)
|
||||
wrb(base + i, cp[i]);
|
||||
|
||||
if (fsegname) {
|
||||
fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
|
||||
for (i = 0; i < 0x10000; i++)
|
||||
wrb(0xf0000 + i, fsegptr[i]);
|
||||
} else {
|
||||
char *date = "01/01/99";
|
||||
for (i = i; date[i]; i++)
|
||||
wrb(0xffff5 + i, date[i]);
|
||||
wrb(0xffff7, '/');
|
||||
wrb(0xffffa, '/');
|
||||
}
|
||||
/* cpu setup */
|
||||
X86_AX = devfn ? devfn : 0xff;
|
||||
X86_DX = 0x80;
|
||||
X86_EIP = initialip;
|
||||
X86_CS = initialcs;
|
||||
|
||||
/* Initialize stack and data segment */
|
||||
X86_SS = 0x0030;
|
||||
X86_DS = 0x0040;
|
||||
X86_SP = 0xfffe;
|
||||
/* We need a sane way to return from bios
|
||||
* execution. A hlt instruction and a pointer
|
||||
* to it, both kept on the stack, will do.
|
||||
*/
|
||||
pushw(0xf4f4); /* hlt; hlt */
|
||||
pushw(X86_SS);
|
||||
pushw(X86_SP + 2);
|
||||
|
||||
X86_ES = 0x0000;
|
||||
|
||||
if (trace) {
|
||||
printf("Switching to single step mode.\n");
|
||||
X86EMU_trace_on();
|
||||
}
|
||||
if (debugflag) {
|
||||
X86EMU_set_debug(debugflag);
|
||||
}
|
||||
X86EMU_exec();
|
||||
/* Cleaning up */
|
||||
pciExit();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef CPU_P6_MSR_H
|
||||
#define CPU_P6_MSR_H
|
||||
|
||||
/*
|
||||
* Access to machine-specific registers (available on 586 and better only)
|
||||
* Note: the rd* operations modify the parameters directly (without using
|
||||
* pointer indirection), this allows gcc to optimize better
|
||||
*/
|
||||
|
||||
#define rdmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("rdmsr" \
|
||||
: "=a" (val1), "=d" (val2) \
|
||||
: "c" (msr))
|
||||
|
||||
#define wrmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("wrmsr" \
|
||||
: /* no outputs */ \
|
||||
: "c" (msr), "a" (val1), "d" (val2))
|
||||
|
||||
#define rdtsc(low,high) \
|
||||
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
|
||||
|
||||
#define rdtscl(low) \
|
||||
__asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
|
||||
|
||||
#define rdtscll(val) \
|
||||
__asm__ __volatile__ ("rdtsc" : "=A" (val))
|
||||
|
||||
#define rdpmc(counter,low,high) \
|
||||
__asm__ __volatile__("rdpmc" \
|
||||
: "=a" (low), "=d" (high) \
|
||||
: "c" (counter))
|
||||
#endif /* CPU_P6_MSR_H */
|
|
@ -0,0 +1,196 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/include/x86emu.h,v 1.2 2000/11/21 23:10:25 tsi Exp $ */
|
||||
|
||||
#ifndef __X86EMU_X86EMU_H
|
||||
#define __X86EMU_X86EMU_H
|
||||
|
||||
#define printk printf
|
||||
|
||||
#ifdef SCITECH
|
||||
#include "scitech.h"
|
||||
#define X86API _ASMAPI
|
||||
#define X86APIP _ASMAPIP
|
||||
typedef int X86EMU_pioAddr;
|
||||
#else
|
||||
#include "x86emu/types.h"
|
||||
#define X86API
|
||||
#define X86APIP *
|
||||
#endif
|
||||
#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() \
|
||||
printk("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 0x000001 /* print decoded instruction */
|
||||
#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */
|
||||
#define DEBUG_STEP_F 0x000004
|
||||
#define DEBUG_DISASSEMBLE_F 0x000008
|
||||
#define DEBUG_BREAK_F 0x000010
|
||||
#define DEBUG_SVC_F 0x000020
|
||||
#define DEBUG_FS_F 0x000080
|
||||
#define DEBUG_PROC_F 0x000100
|
||||
#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */
|
||||
#define DEBUG_TRACECALL_F 0x000400
|
||||
#define DEBUG_INSTRUMENT_F 0x000800
|
||||
#define DEBUG_MEM_TRACE_F 0x001000
|
||||
#define DEBUG_IO_TRACE_F 0x002000
|
||||
#define DEBUG_TRACECALL_REGS_F 0x004000
|
||||
#define DEBUG_DECODE_NOPRINT_F 0x008000
|
||||
#define DEBUG_SAVE_IP_CS_F 0x010000
|
||||
#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 */
|
|
@ -0,0 +1,115 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 FPU register definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_FPU_REGS_H
|
||||
#define __X86EMU_FPU_REGS_H
|
||||
|
||||
#ifdef X86_FPU_SUPPORT
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Basic 8087 register can hold any of the following values: */
|
||||
|
||||
union x86_fpu_reg_u {
|
||||
s8 tenbytes[10];
|
||||
double dval;
|
||||
float fval;
|
||||
s16 sval;
|
||||
s32 lval;
|
||||
};
|
||||
|
||||
struct x86_fpu_reg {
|
||||
union x86_fpu_reg_u reg;
|
||||
char tag;
|
||||
};
|
||||
|
||||
/*
|
||||
* Since we are not going to worry about the problems of aliasing
|
||||
* registers, every time a register is modified, its result type is
|
||||
* set in the tag fields for that register. If some operation
|
||||
* attempts to access the type in a way inconsistent with its current
|
||||
* storage format, then we flag the operation. If common, we'll
|
||||
* attempt the conversion.
|
||||
*/
|
||||
|
||||
#define X86_FPU_VALID 0x80
|
||||
#define X86_FPU_REGTYP(r) ((r) & 0x7F)
|
||||
|
||||
#define X86_FPU_WORD 0x0
|
||||
#define X86_FPU_SHORT 0x1
|
||||
#define X86_FPU_LONG 0x2
|
||||
#define X86_FPU_FLOAT 0x3
|
||||
#define X86_FPU_DOUBLE 0x4
|
||||
#define X86_FPU_LDBL 0x5
|
||||
#define X86_FPU_BSD 0x6
|
||||
|
||||
#define X86_FPU_STKTOP 0
|
||||
|
||||
struct x86_fpu_registers {
|
||||
struct x86_fpu_reg x86_fpu_stack[8];
|
||||
int x86_fpu_flags;
|
||||
int x86_fpu_config; /* rounding modes, etc. */
|
||||
short x86_fpu_tos, x86_fpu_bos;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/*
|
||||
* There are two versions of the following macro.
|
||||
*
|
||||
* One version is for opcode D9, for which there are more than 32
|
||||
* instructions encoded in the second byte of the opcode.
|
||||
*
|
||||
* The other version, deals with all the other 7 i87 opcodes, for
|
||||
* which there are only 32 strings needed to describe the
|
||||
* instructions.
|
||||
*/
|
||||
|
||||
#endif /* X86_FPU_SUPPORT */
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DECODE_PRINTINSTR32(t,mod,rh,rl) \
|
||||
DECODE_PRINTF(t[(mod<<3)+(rh)]);
|
||||
# define DECODE_PRINTINSTR256(t,mod,rh,rl) \
|
||||
DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]);
|
||||
#else
|
||||
# define DECODE_PRINTINSTR32(t,mod,rh,rl)
|
||||
# define DECODE_PRINTINSTR256(t,mod,rh,rl)
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_FPU_REGS_H */
|
|
@ -0,0 +1,336 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 x86 register definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/include/x86emu/regs.h,v 1.3 2001/10/28 03:32:25 tsi Exp $ */
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
u32 mode;
|
||||
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
|
||||
u8 intno;
|
||||
u8 __pad[3];
|
||||
} X86EMU_regs;
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Structure maintaining the emulator machine state.
|
||||
|
||||
MEMBERS:
|
||||
mem_base - Base real mode memory for the emulator
|
||||
abseg - Base for the absegment
|
||||
mem_size - Size of the real mode memory block for the emulator
|
||||
private - private data pointer
|
||||
x86 - X86 registers
|
||||
****************************************************************************/
|
||||
typedef struct {
|
||||
unsigned long mem_base;
|
||||
unsigned long mem_size;
|
||||
unsigned long abseg;
|
||||
void* private;
|
||||
X86EMU_regs x86;
|
||||
} 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 */
|
||||
|
||||
//void printk(const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_REGS_H */
|
|
@ -0,0 +1,89 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 x86 emulator type definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.4 2000/09/26 15:56:44 tsi Exp $ */
|
||||
|
||||
#ifndef __X86EMU_TYPES_H
|
||||
#define __X86EMU_TYPES_H
|
||||
|
||||
#ifndef IN_MODULE
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following kludge is an attempt to work around typedef conflicts with
|
||||
* <sys/types.h>.
|
||||
*/
|
||||
#define u8 x86emuu8
|
||||
#define u16 x86emuu16
|
||||
#define u32 x86emuu32
|
||||
#define u64 x86emuu64
|
||||
#define s8 x86emus8
|
||||
#define s16 x86emus16
|
||||
#define s32 x86emus32
|
||||
#define s64 x86emus64
|
||||
#define uint x86emuuint
|
||||
#define sint x86emusint
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
/* Currently only for Linux/32bit */
|
||||
#if defined(__GNUC__) && !defined(NO_LONG_LONG)
|
||||
#define __HAS_LONG_LONG__
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#ifdef __HAS_LONG_LONG__
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
typedef char s8;
|
||||
typedef short s16;
|
||||
typedef int s32;
|
||||
#ifdef __HAS_LONG_LONG__
|
||||
typedef long long s64;
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef int sint;
|
||||
|
||||
typedef u16 X86EMU_pioAddr;
|
||||
|
||||
#endif /* __X86EMU_TYPES_H */
|
|
@ -0,0 +1,17 @@
|
|||
License information
|
||||
-------------------
|
||||
|
||||
The x86emu library is under a BSD style license, comaptible
|
||||
with the XFree86 and X licenses used by XFree86. The
|
||||
original x86emu libraries were under the GNU General Public
|
||||
License. Due to license incompatibilities between the GPL
|
||||
and the XFree86 license, the original authors of the code
|
||||
decided to allow a license change. If you have submitted
|
||||
code to the original x86emu project, and you don't agree
|
||||
with the license change, please contact us and let you
|
||||
know. Your code will be removed to comply with your wishes.
|
||||
|
||||
If you have any questions about this, please send email to
|
||||
x86emu@linuxlabs.com or KendallB@scitechsoft.com for
|
||||
clarification.
|
||||
|
|
@ -0,0 +1,471 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1996-1999 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file contains the code to handle debugging of the
|
||||
* emulator.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/debug.c,v 1.4 2000/04/17 16:29:45 eich Exp $ */
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
#ifdef IN_MODULE
|
||||
#include "xf86_ansic.h"
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*----------------------------- 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("%x:%x -", M.x86.saved_cs, offset);
|
||||
p = fgets(s, 1023, stdin);
|
||||
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':
|
||||
exit(1);
|
||||
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);
|
||||
}
|
||||
|
||||
int X86EMU_set_debug(int debug)
|
||||
{
|
||||
return M.x86.debug = debug;
|
||||
}
|
||||
|
||||
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++;
|
||||
|
||||
sscanf(s, "%x", &ps[*n]);
|
||||
*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");
|
||||
}
|
|
@ -0,0 +1,832 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1996-1999 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file includes subroutines which are related to
|
||||
* instruction decoding and accessess of immediate data via IP. etc.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/decode.c,v 1.9 2001/01/06 20:19:03 tsi Exp $ */
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Handles any pending asychronous interrupts.
|
||||
****************************************************************************/
|
||||
static void x86emu_intr_handle(void)
|
||||
{
|
||||
u8 intno;
|
||||
|
||||
if (M.x86.intr & INTR_SYNCH) {
|
||||
intno = M.x86.intno;
|
||||
if (_X86EMU_intrTab[intno]) {
|
||||
(*_X86EMU_intrTab[intno]) (intno);
|
||||
} else {
|
||||
push_word((u16) M.x86.R_FLG);
|
||||
CLEAR_FLAG(F_IF);
|
||||
CLEAR_FLAG(F_TF);
|
||||
push_word(M.x86.R_CS);
|
||||
M.x86.R_CS = mem_access_word(intno * 4 + 2);
|
||||
push_word(M.x86.R_IP);
|
||||
M.x86.R_IP = mem_access_word(intno * 4);
|
||||
M.x86.intr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
intrnum - Interrupt number to raise
|
||||
|
||||
REMARKS:
|
||||
Raise the specified interrupt to be handled before the execution of the
|
||||
next instruction.
|
||||
****************************************************************************/
|
||||
void x86emu_intr_raise(u8 intrnum)
|
||||
{
|
||||
M.x86.intno = intrnum;
|
||||
M.x86.intr |= INTR_SYNCH;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Main execution loop for the emulator. We return from here when the system
|
||||
halts, which is normally caused by a stack fault when we return from the
|
||||
original real mode call.
|
||||
****************************************************************************/
|
||||
void X86EMU_exec(void)
|
||||
{
|
||||
u8 op1;
|
||||
|
||||
M.x86.intr = 0;
|
||||
DB(x86emu_end_instr();
|
||||
)
|
||||
|
||||
for (;;) {
|
||||
DB(if (CHECK_IP_FETCH())
|
||||
x86emu_check_ip_access();)
|
||||
/* If debugging, save the IP and CS values. */
|
||||
SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
|
||||
INC_DECODED_INST_LEN(1);
|
||||
if (M.x86.intr) {
|
||||
if (M.x86.intr & INTR_HALTED) {
|
||||
DB(printk("halted\n"); X86EMU_trace_regs();
|
||||
)
|
||||
return;
|
||||
}
|
||||
if (((M.x86.intr & INTR_SYNCH)
|
||||
&& (M.x86.intno == 0 || M.x86.intno == 2))
|
||||
|| !ACCESS_FLAG(F_IF)) {
|
||||
x86emu_intr_handle();
|
||||
}
|
||||
}
|
||||
op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
|
||||
(*x86emu_optab[op1]) (op1);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Halts the system by setting the halted system flag.
|
||||
****************************************************************************/
|
||||
void X86EMU_halt_sys(void)
|
||||
{
|
||||
M.x86.intr |= INTR_HALTED;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
mod - Mod value from decoded byte
|
||||
regh - Reg h value from decoded byte
|
||||
regl - Reg l value from decoded byte
|
||||
|
||||
REMARKS:
|
||||
Raise the specified interrupt to be handled before the execution of the
|
||||
next instruction.
|
||||
|
||||
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
|
||||
****************************************************************************/
|
||||
void fetch_decode_modrm(int *mod, int *regh, int *regl)
|
||||
{
|
||||
int fetched;
|
||||
|
||||
DB(if (CHECK_IP_FETCH())
|
||||
x86emu_check_ip_access();)
|
||||
fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
|
||||
INC_DECODED_INST_LEN(1);
|
||||
*mod = (fetched >> 6) & 0x03;
|
||||
*regh = (fetched >> 3) & 0x07;
|
||||
*regl = (fetched >> 0) & 0x07;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
RETURNS:
|
||||
Immediate byte value read from instruction queue
|
||||
|
||||
REMARKS:
|
||||
This function returns the immediate byte from the instruction queue, and
|
||||
moves the instruction pointer to the next value.
|
||||
|
||||
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
|
||||
****************************************************************************/
|
||||
u8 fetch_byte_imm(void)
|
||||
{
|
||||
u8 fetched;
|
||||
|
||||
DB(if (CHECK_IP_FETCH())
|
||||
x86emu_check_ip_access();)
|
||||
fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
|
||||
INC_DECODED_INST_LEN(1);
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
RETURNS:
|
||||
Immediate word value read from instruction queue
|
||||
|
||||
REMARKS:
|
||||
This function returns the immediate byte from the instruction queue, and
|
||||
moves the instruction pointer to the next value.
|
||||
|
||||
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
|
||||
****************************************************************************/
|
||||
u16 fetch_word_imm(void)
|
||||
{
|
||||
u16 fetched;
|
||||
|
||||
DB(if (CHECK_IP_FETCH())
|
||||
x86emu_check_ip_access();)
|
||||
fetched = (*sys_rdw) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP));
|
||||
M.x86.R_IP += 2;
|
||||
INC_DECODED_INST_LEN(2);
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
RETURNS:
|
||||
Immediate lone value read from instruction queue
|
||||
|
||||
REMARKS:
|
||||
This function returns the immediate byte from the instruction queue, and
|
||||
moves the instruction pointer to the next value.
|
||||
|
||||
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
|
||||
****************************************************************************/
|
||||
u32 fetch_long_imm(void)
|
||||
{
|
||||
u32 fetched;
|
||||
|
||||
DB(if (CHECK_IP_FETCH())
|
||||
x86emu_check_ip_access();)
|
||||
fetched = (*sys_rdl) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP));
|
||||
M.x86.R_IP += 4;
|
||||
INC_DECODED_INST_LEN(4);
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
RETURNS:
|
||||
Value of the default data segment
|
||||
|
||||
REMARKS:
|
||||
Inline function that returns the default data segment for the current
|
||||
instruction.
|
||||
|
||||
On the x86 processor, the default segment is not always DS if there is
|
||||
no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
|
||||
addresses relative to SS (ie: on the stack). So, at the minimum, all
|
||||
decodings of addressing modes would have to set/clear a bit describing
|
||||
whether the access is relative to DS or SS. That is the function of the
|
||||
cpu-state-varible M.x86.mode. There are several potential states:
|
||||
|
||||
repe prefix seen (handled elsewhere)
|
||||
repne prefix seen (ditto)
|
||||
|
||||
cs segment override
|
||||
ds segment override
|
||||
es segment override
|
||||
fs segment override
|
||||
gs segment override
|
||||
ss segment override
|
||||
|
||||
ds/ss select (in absense of override)
|
||||
|
||||
Each of the above 7 items are handled with a bit in the mode field.
|
||||
****************************************************************************/
|
||||
_INLINE u32 get_data_segment(void)
|
||||
{
|
||||
#define GET_SEGMENT(segment)
|
||||
switch (M.x86.mode & SYSMODE_SEGMASK) {
|
||||
case 0: /* default case: use ds register */
|
||||
case SYSMODE_SEGOVR_DS:
|
||||
case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_DS;
|
||||
case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
|
||||
return M.x86.R_SS;
|
||||
case SYSMODE_SEGOVR_CS:
|
||||
case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_CS;
|
||||
case SYSMODE_SEGOVR_ES:
|
||||
case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_ES;
|
||||
case SYSMODE_SEGOVR_FS:
|
||||
case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_FS;
|
||||
case SYSMODE_SEGOVR_GS:
|
||||
case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_GS;
|
||||
case SYSMODE_SEGOVR_SS:
|
||||
case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
|
||||
return M.x86.R_SS;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printk("error: should not happen: multiple overrides.\n");
|
||||
#endif
|
||||
HALT_SYS();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Byte value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u8 fetch_data_byte(uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
return (*sys_rdb) ((get_data_segment() << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Word value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u16 fetch_data_word(uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
return (*sys_rdw) ((get_data_segment() << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Long value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u32 fetch_data_long(uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
return (*sys_rdl) ((get_data_segment() << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to load data from
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Byte value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u8 fetch_data_byte_abs(uint segment, uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
return (*sys_rdb) (((u32) segment << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to load data from
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Word value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u16 fetch_data_word_abs(uint segment, uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
return (*sys_rdw) (((u32) segment << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to load data from
|
||||
offset - Offset to load data from
|
||||
|
||||
RETURNS:
|
||||
Long value read from the absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_rdX) is already inline!
|
||||
****************************************************************************/
|
||||
u32 fetch_data_long_abs(uint segment, uint offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
return (*sys_rdl) (((u32) segment << 4) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a word value to an segmented memory location. The segment used is
|
||||
the current 'default' segment, which may have been overridden.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_byte(uint offset, u8 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
(*sys_wrb) ((get_data_segment() << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a word value to an segmented memory location. The segment used is
|
||||
the current 'default' segment, which may have been overridden.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_word(uint offset, u16 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
(*sys_wrw) ((get_data_segment() << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a long value to an segmented memory location. The segment used is
|
||||
the current 'default' segment, which may have been overridden.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_long(uint offset, u32 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access((u16) get_data_segment(), offset);
|
||||
#endif
|
||||
(*sys_wrl) ((get_data_segment() << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to store data at
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a byte value to an absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_byte_abs(uint segment, uint offset, u8 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
(*sys_wrb) (((u32) segment << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to store data at
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a word value to an absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_word_abs(uint segment, uint offset, u16 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
(*sys_wrw) (((u32) segment << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
segment - Segment to store data at
|
||||
offset - Offset to store data at
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a long value to an absolute memory location.
|
||||
|
||||
NOTE: Do not inline this function as (*sys_wrX) is already inline!
|
||||
****************************************************************************/
|
||||
void store_data_long_abs(uint segment, uint offset, u32 val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (CHECK_DATA_ACCESS())
|
||||
x86emu_check_data_access(segment, offset);
|
||||
#endif
|
||||
(*sys_wrl) (((u32) segment << 4) + offset, val);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
reg - Register to decode
|
||||
|
||||
RETURNS:
|
||||
Pointer to the appropriate register
|
||||
|
||||
REMARKS:
|
||||
Return a pointer to the register given by the R/RM field of the
|
||||
modrm byte, for byte operands. Also enables the decoding of instructions.
|
||||
****************************************************************************/
|
||||
u8 *decode_rm_byte_register(int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
DECODE_PRINTF("AL");
|
||||
return &M.x86.R_AL;
|
||||
case 1:
|
||||
DECODE_PRINTF("CL");
|
||||
return &M.x86.R_CL;
|
||||
case 2:
|
||||
DECODE_PRINTF("DL");
|
||||
return &M.x86.R_DL;
|
||||
case 3:
|
||||
DECODE_PRINTF("BL");
|
||||
return &M.x86.R_BL;
|
||||
case 4:
|
||||
DECODE_PRINTF("AH");
|
||||
return &M.x86.R_AH;
|
||||
case 5:
|
||||
DECODE_PRINTF("CH");
|
||||
return &M.x86.R_CH;
|
||||
case 6:
|
||||
DECODE_PRINTF("DH");
|
||||
return &M.x86.R_DH;
|
||||
case 7:
|
||||
DECODE_PRINTF("BH");
|
||||
return &M.x86.R_BH;
|
||||
}
|
||||
HALT_SYS();
|
||||
return NULL; /* NOT REACHED OR REACHED ON ERROR */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
reg - Register to decode
|
||||
|
||||
RETURNS:
|
||||
Pointer to the appropriate register
|
||||
|
||||
REMARKS:
|
||||
Return a pointer to the register given by the R/RM field of the
|
||||
modrm byte, for word operands. Also enables the decoding of instructions.
|
||||
****************************************************************************/
|
||||
u16 *decode_rm_word_register(int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
DECODE_PRINTF("AX");
|
||||
return &M.x86.R_AX;
|
||||
case 1:
|
||||
DECODE_PRINTF("CX");
|
||||
return &M.x86.R_CX;
|
||||
case 2:
|
||||
DECODE_PRINTF("DX");
|
||||
return &M.x86.R_DX;
|
||||
case 3:
|
||||
DECODE_PRINTF("BX");
|
||||
return &M.x86.R_BX;
|
||||
case 4:
|
||||
DECODE_PRINTF("SP");
|
||||
return &M.x86.R_SP;
|
||||
case 5:
|
||||
DECODE_PRINTF("BP");
|
||||
return &M.x86.R_BP;
|
||||
case 6:
|
||||
DECODE_PRINTF("SI");
|
||||
return &M.x86.R_SI;
|
||||
case 7:
|
||||
DECODE_PRINTF("DI");
|
||||
return &M.x86.R_DI;
|
||||
}
|
||||
HALT_SYS();
|
||||
return NULL; /* NOTREACHED OR REACHED ON ERROR */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
reg - Register to decode
|
||||
|
||||
RETURNS:
|
||||
Pointer to the appropriate register
|
||||
|
||||
REMARKS:
|
||||
Return a pointer to the register given by the R/RM field of the
|
||||
modrm byte, for dword operands. Also enables the decoding of instructions.
|
||||
****************************************************************************/
|
||||
u32 *decode_rm_long_register(int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
DECODE_PRINTF("EAX");
|
||||
return &M.x86.R_EAX;
|
||||
case 1:
|
||||
DECODE_PRINTF("ECX");
|
||||
return &M.x86.R_ECX;
|
||||
case 2:
|
||||
DECODE_PRINTF("EDX");
|
||||
return &M.x86.R_EDX;
|
||||
case 3:
|
||||
DECODE_PRINTF("EBX");
|
||||
return &M.x86.R_EBX;
|
||||
case 4:
|
||||
DECODE_PRINTF("ESP");
|
||||
return &M.x86.R_ESP;
|
||||
case 5:
|
||||
DECODE_PRINTF("EBP");
|
||||
return &M.x86.R_EBP;
|
||||
case 6:
|
||||
DECODE_PRINTF("ESI");
|
||||
return &M.x86.R_ESI;
|
||||
case 7:
|
||||
DECODE_PRINTF("EDI");
|
||||
return &M.x86.R_EDI;
|
||||
}
|
||||
HALT_SYS();
|
||||
return NULL; /* NOTREACHED OR REACHED ON ERROR */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
reg - Register to decode
|
||||
|
||||
RETURNS:
|
||||
Pointer to the appropriate register
|
||||
|
||||
REMARKS:
|
||||
Return a pointer to the register given by the R/RM field of the
|
||||
modrm byte, for word operands, modified from above for the weirdo
|
||||
special case of segreg operands. Also enables the decoding of instructions.
|
||||
****************************************************************************/
|
||||
u16 *decode_rm_seg_register(int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
DECODE_PRINTF("ES");
|
||||
return &M.x86.R_ES;
|
||||
case 1:
|
||||
DECODE_PRINTF("CS");
|
||||
return &M.x86.R_CS;
|
||||
case 2:
|
||||
DECODE_PRINTF("SS");
|
||||
return &M.x86.R_SS;
|
||||
case 3:
|
||||
DECODE_PRINTF("DS");
|
||||
return &M.x86.R_DS;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
DECODE_PRINTF("ILLEGAL SEGREG");
|
||||
break;
|
||||
}
|
||||
HALT_SYS();
|
||||
return NULL; /* NOT REACHED OR REACHED ON ERROR */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
rm - RM value to decode
|
||||
|
||||
RETURNS:
|
||||
Offset in memory for the address decoding
|
||||
|
||||
REMARKS:
|
||||
Return the offset given by mod=00 addressing. Also enables the
|
||||
decoding of instructions.
|
||||
|
||||
NOTE: The code which specifies the corresponding segment (ds vs ss)
|
||||
below in the case of [BP+..]. The assumption here is that at the
|
||||
point that this subroutine is called, the bit corresponding to
|
||||
SYSMODE_SEG_DS_SS will be zero. After every instruction
|
||||
except the segment override instructions, this bit (as well
|
||||
as any bits indicating segment overrides) will be clear. So
|
||||
if a SS access is needed, set this bit. Otherwise, DS access
|
||||
occurs (unless any of the segment override bits are set).
|
||||
****************************************************************************/
|
||||
unsigned decode_rm00_address(int rm)
|
||||
{
|
||||
unsigned offset;
|
||||
|
||||
switch (rm) {
|
||||
case 0:
|
||||
DECODE_PRINTF("[BX+SI]");
|
||||
return M.x86.R_BX + M.x86.R_SI;
|
||||
case 1:
|
||||
DECODE_PRINTF("[BX+DI]");
|
||||
return M.x86.R_BX + M.x86.R_DI;
|
||||
case 2:
|
||||
DECODE_PRINTF("[BP+SI]");
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_SI;
|
||||
case 3:
|
||||
DECODE_PRINTF("[BP+DI]");
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_DI;
|
||||
case 4:
|
||||
DECODE_PRINTF("[SI]");
|
||||
return M.x86.R_SI;
|
||||
case 5:
|
||||
DECODE_PRINTF("[DI]");
|
||||
return M.x86.R_DI;
|
||||
case 6:
|
||||
offset = fetch_word_imm();
|
||||
DECODE_PRINTF2("[%04x]", offset);
|
||||
return offset;
|
||||
case 7:
|
||||
DECODE_PRINTF("[BX]");
|
||||
return M.x86.R_BX;
|
||||
}
|
||||
HALT_SYS();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
rm - RM value to decode
|
||||
|
||||
RETURNS:
|
||||
Offset in memory for the address decoding
|
||||
|
||||
REMARKS:
|
||||
Return the offset given by mod=01 addressing. Also enables the
|
||||
decoding of instructions.
|
||||
****************************************************************************/
|
||||
unsigned decode_rm01_address(int rm)
|
||||
{
|
||||
int displacement = (s8) fetch_byte_imm();
|
||||
switch (rm) {
|
||||
case 0:
|
||||
DECODE_PRINTF2("%d[BX+SI]", displacement);
|
||||
return M.x86.R_BX + M.x86.R_SI + displacement;
|
||||
case 1:
|
||||
DECODE_PRINTF2("%d[BX+DI]", displacement);
|
||||
return M.x86.R_BX + M.x86.R_DI + displacement;
|
||||
case 2:
|
||||
DECODE_PRINTF2("%d[BP+SI]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_SI + displacement;
|
||||
case 3:
|
||||
DECODE_PRINTF2("%d[BP+DI]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_DI + displacement;
|
||||
case 4:
|
||||
DECODE_PRINTF2("%d[SI]", displacement);
|
||||
return M.x86.R_SI + displacement;
|
||||
case 5:
|
||||
DECODE_PRINTF2("%d[DI]", displacement);
|
||||
return M.x86.R_DI + displacement;
|
||||
case 6:
|
||||
DECODE_PRINTF2("%d[BP]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + displacement;
|
||||
case 7:
|
||||
DECODE_PRINTF2("%d[BX]", displacement);
|
||||
return M.x86.R_BX + displacement;
|
||||
}
|
||||
HALT_SYS();
|
||||
return 0; /* SHOULD NOT HAPPEN */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
rm - RM value to decode
|
||||
|
||||
RETURNS:
|
||||
Offset in memory for the address decoding
|
||||
|
||||
REMARKS:
|
||||
Return the offset given by mod=10 addressing. Also enables the
|
||||
decoding of instructions.
|
||||
****************************************************************************/
|
||||
unsigned decode_rm10_address(int rm)
|
||||
{
|
||||
unsigned displacement = (u16) fetch_word_imm();
|
||||
switch (rm) {
|
||||
case 0:
|
||||
DECODE_PRINTF2("%04x[BX+SI]", displacement);
|
||||
return M.x86.R_BX + M.x86.R_SI + displacement;
|
||||
case 1:
|
||||
DECODE_PRINTF2("%04x[BX+DI]", displacement);
|
||||
return M.x86.R_BX + M.x86.R_DI + displacement;
|
||||
case 2:
|
||||
DECODE_PRINTF2("%04x[BP+SI]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_SI + displacement;
|
||||
case 3:
|
||||
DECODE_PRINTF2("%04x[BP+DI]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + M.x86.R_DI + displacement;
|
||||
case 4:
|
||||
DECODE_PRINTF2("%04x[SI]", displacement);
|
||||
return M.x86.R_SI + displacement;
|
||||
case 5:
|
||||
DECODE_PRINTF2("%04x[DI]", displacement);
|
||||
return M.x86.R_DI + displacement;
|
||||
case 6:
|
||||
DECODE_PRINTF2("%04x[BP]", displacement);
|
||||
M.x86.mode |= SYSMODE_SEG_DS_SS;
|
||||
return M.x86.R_BP + displacement;
|
||||
case 7:
|
||||
DECODE_PRINTF2("%04x[BX]", displacement);
|
||||
return M.x86.R_BX + displacement;
|
||||
}
|
||||
HALT_SYS();
|
||||
return 0;
|
||||
/*NOTREACHED */
|
||||
}
|
|
@ -0,0 +1,944 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1996-1999 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file contains the code to implement the decoding and
|
||||
* emulation of the FPU instructions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
/* opcode=0xd8 */
|
||||
void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
START_OF_INSTR();
|
||||
DECODE_PRINTF("ESC D8\n");
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_d9_tab[] = {
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
};
|
||||
|
||||
static char *x86emu_fpu_op_d9_tab1[] = {
|
||||
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
|
||||
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
|
||||
|
||||
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
|
||||
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
|
||||
|
||||
"FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
|
||||
"ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
|
||||
|
||||
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
|
||||
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
|
||||
|
||||
"FCHS", "FABS", "ESC_D9", "ESC_D9",
|
||||
"FTST", "FXAM", "ESC_D9", "ESC_D9",
|
||||
|
||||
"FLD1", "FLDL2T", "FLDL2E", "FLDPI",
|
||||
"FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
|
||||
|
||||
"F2XM1", "FYL2X", "FPTAN", "FPATAN",
|
||||
"FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
|
||||
|
||||
"FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
|
||||
"FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xd9 */
|
||||
void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DEBUG
|
||||
if (mod != 3) {
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
|
||||
} else {
|
||||
DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
|
||||
}
|
||||
#endif
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
if (rh < 4) {
|
||||
DECODE_PRINTF2("ST(%d)\n", stkelem);
|
||||
} else {
|
||||
DECODE_PRINTF("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 2:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_nop();
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 4:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
default:
|
||||
/* 2,3,6,7 */
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
default:
|
||||
/* 7 */
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_decstp();
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_incstp();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* X86EMU_FPU_PRESENT */
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
char *x86emu_fpu_op_da_tab[] = {
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
|
||||
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xda */
|
||||
void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
char *x86emu_fpu_op_db_tab[] = {
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdb */
|
||||
void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DEBUG
|
||||
if (mod != 3) {
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
|
||||
} else if (rh == 4) { /* === 11 10 0 nnn */
|
||||
switch (rl) {
|
||||
case 0:
|
||||
DECODE_PRINTF("FENI\n");
|
||||
break;
|
||||
case 1:
|
||||
DECODE_PRINTF("FDISI\n");
|
||||
break;
|
||||
case 2:
|
||||
DECODE_PRINTF("FCLEX\n");
|
||||
break;
|
||||
case 3:
|
||||
DECODE_PRINTF("FINIT\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 4:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_feni();
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fdisi();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fclex();
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_finit();
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
char *x86emu_fpu_op_dc_tab[] = {
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
|
||||
"FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdc */
|
||||
void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_dd_tab[] = {
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
|
||||
"ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdd */
|
||||
void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_ffree(stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(stkelem);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fst(stkelem); /* register version */
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(stkelem); /* register version */
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_de_tab[] = {
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
|
||||
"FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xde */
|
||||
void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
if (stkelem == 1)
|
||||
x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
|
||||
else
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_df_tab[] = {
|
||||
/* mod == 00 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 01 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 10 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 11 */
|
||||
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
|
||||
"ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdf */
|
||||
void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset;
|
||||
u8 stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8) rl;
|
||||
DECODE_PRINTF2("\tST(%d)\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_ffree(stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(stkelem);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fst(stkelem); /* register version */
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(stkelem); /* register version */
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#############################################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ========================================================================
|
||||
#
|
||||
# Descripton: Generic makefile for the x86emu library. Requires
|
||||
# the SciTech Software makefile definitions package to be
|
||||
# installed, which uses the DMAKE make program.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
.IMPORT .IGNORE: DEBUG
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the lists of object files
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
OBJECTS = sys$O decode$O ops$O ops2$O prim_ops$O fpu$O debug$O
|
||||
CFLAGS += -DSCITECH
|
||||
.IF $(DEBUG)
|
||||
CFLAGS += -DDEBUG
|
||||
.ENDIF
|
||||
LIBCLEAN = *.dll *.lib *.a
|
||||
LIBFILE = $(LP)x86emu$L
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Sample test programs
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
all: $(LIBFILE)
|
||||
|
||||
validate$E: validate$O $(LIBFILE)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the list of object files to create dependency information for
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
DEPEND_OBJ = validate$O $(OBJECTS)
|
||||
|
||||
.INCLUDE: "$(SCITECH)/makedefs/common.mk"
|
|
@ -0,0 +1,60 @@
|
|||
#############################################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ========================================================================
|
||||
#
|
||||
# Descripton: Linux specific makefile for the x86emu library.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
TARGETLIB = libx86emu.a
|
||||
|
||||
OBJS=\
|
||||
debug.o \
|
||||
decode.o \
|
||||
fpu.o \
|
||||
ops.o \
|
||||
ops2.o \
|
||||
prim_ops.o \
|
||||
sys.o
|
||||
|
||||
$(TARGETLIB): $(OBJS)
|
||||
ar rv $(TARGETLIB) $(OBJS)
|
||||
|
||||
INCS = -I. -Ix86emu -I../../include
|
||||
CFLAGS = -D__DRIVER__ -DFORCE_POST -D_CEXPORT= -DNO_LONG_LONG -DDEBUG
|
||||
|
||||
.c.o:
|
||||
gcc -g -O -Wall -c $(CFLAGS) $(INCS) $*.c
|
||||
|
||||
.cpp.o:
|
||||
gcc -c $(CFLAGS) $(INCS) $*.cpp
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o
|
||||
|
||||
validate: validate.o libx86emu.a
|
||||
gcc -o validate validate.o -lx86emu -L.
|
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
|
@ -0,0 +1,606 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1996-1999 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file includes subroutines which are related to
|
||||
* programmed I/O and memory access. Included in this module
|
||||
* are default functions with limited usefulness. For real
|
||||
* uses these functions will most likely be overriden by the
|
||||
* user library.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/sys.c,v 1.5 2000/08/23 22:10:01 tsi Exp $ */
|
||||
|
||||
#include "x86emu.h"
|
||||
#include "x86emu/regs.h"
|
||||
#include "x86emu/debug.h"
|
||||
#include "x86emu/prim_ops.h"
|
||||
#include <sys/io.h>
|
||||
#ifdef IN_MODULE
|
||||
#include "xf86_ansic.h"
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
/*------------------------- Global Variables ------------------------------*/
|
||||
|
||||
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
|
||||
X86EMU_intrFuncs _X86EMU_intrTab[256];
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
/* to cope with broken egcs-1.1.2 :-(((( */
|
||||
|
||||
/*
|
||||
* inline functions to do unaligned accesses
|
||||
* from linux/include/asm-alpha/unaligned.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* EGCS 1.1 knows about arbitrary unaligned loads. Define some
|
||||
* packed structures to talk about such things with.
|
||||
*/
|
||||
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
struct __una_u64 {
|
||||
unsigned long x __attribute__ ((packed));
|
||||
};
|
||||
struct __una_u32 {
|
||||
unsigned int x __attribute__ ((packed));
|
||||
};
|
||||
struct __una_u16 {
|
||||
unsigned short x __attribute__ ((packed));
|
||||
};
|
||||
#endif
|
||||
|
||||
static __inline__ unsigned long ldq_u(unsigned long *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1, r2;
|
||||
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extql %0,%2,%0\n\t" "extqh %1,%2,%1":"=&r"(r1),
|
||||
"=&r"
|
||||
(r2)
|
||||
: "r"(r11), "m"(*r11),
|
||||
"m"(*(const unsigned long *) (7 + (char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ unsigned long ldl_u(unsigned int *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1, r2;
|
||||
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extll %0,%2,%0\n\t" "extlh %1,%2,%1":"=&r"(r1),
|
||||
"=&r"
|
||||
(r2)
|
||||
: "r"(r11), "m"(*r11),
|
||||
"m"(*(const unsigned long *) (3 + (char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ unsigned long ldw_u(unsigned short *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1, r2;
|
||||
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extwl %0,%2,%0\n\t" "extwh %1,%2,%1":"=&r"(r1),
|
||||
"=&r"
|
||||
(r2)
|
||||
: "r"(r11), "m"(*r11),
|
||||
"m"(*(const unsigned long *) (1 + (char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Elemental unaligned stores
|
||||
*/
|
||||
|
||||
static __inline__ void stq_u(unsigned long r5, unsigned long *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
struct __una_u64 *ptr = (struct __una_u64 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1, r2, r3, r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "insqh %6,%7,%5\n\t" "insql %6,%7,%4\n\t" "mskqh %3,%7,%3\n\t" "mskql %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
|
||||
"=m"(*(unsigned long *) (7 + (char *) r11)),
|
||||
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
|
||||
: "r"(r5), "r"(r11));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void stl_u(unsigned long r5, unsigned int *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
struct __una_u32 *ptr = (struct __una_u32 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1, r2, r3, r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inslh %6,%7,%5\n\t" "insll %6,%7,%4\n\t" "msklh %3,%7,%3\n\t" "mskll %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
|
||||
"=m"(*(unsigned long *) (3 + (char *) r11)),
|
||||
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
|
||||
: "r"(r5), "r"(r11));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void stw_u(unsigned long r5, unsigned short *r11)
|
||||
{
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
|
||||
struct __una_u16 *ptr = (struct __una_u16 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1, r2, r3, r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inswh %6,%7,%5\n\t" "inswl %6,%7,%4\n\t" "mskwh %3,%7,%3\n\t" "mskwl %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
|
||||
"=m"(*(unsigned long *) (1 + (char *) r11)),
|
||||
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
|
||||
: "r"(r5), "r"(r11));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* compute a pointer. This replaces code scattered all over the place! */
|
||||
u8 *mem_ptr(u32 addr, int size)
|
||||
{
|
||||
u8 *retaddr = 0;
|
||||
|
||||
if (addr > M.mem_size - size) {
|
||||
DB(printk("mem_ptr: address %#lx out of range!\n", addr);
|
||||
)
|
||||
HALT_SYS();
|
||||
}
|
||||
/* a or b segment? */
|
||||
/* & with e to clear low-order bit, if it is a or b it will be a */
|
||||
if (((addr & 0xfffe0000) == 0xa0000) && M.abseg) {
|
||||
//printk("It's a0000\n");
|
||||
addr &= ~0xfffe0000;
|
||||
retaddr = (u8 *) (M.abseg + addr);
|
||||
//printk("retaddr now 0x%p\n", retaddr);
|
||||
} else if (addr < 0x200) {
|
||||
//printk("updating int vector 0x%x\n", addr >> 2);
|
||||
retaddr = (u8 *) (M.mem_base + addr);
|
||||
} else {
|
||||
retaddr = (u8 *) (M.mem_base + addr);
|
||||
}
|
||||
return retaddr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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)
|
||||
{
|
||||
u8 val;
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 1);
|
||||
|
||||
val = *ptr;
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 1 -> %#x\n", addr, val);)
|
||||
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.
|
||||
****************************************************************************/
|
||||
u16 X86API rdw(u32 addr)
|
||||
{
|
||||
u16 val = 0;
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 2);
|
||||
|
||||
if (addr > M.mem_size - 2) {
|
||||
DB(printk("mem_read: address %#lx out of range!\n", (unsigned long) addr);
|
||||
)
|
||||
HALT_SYS();
|
||||
}
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
val = (*ptr | (*(ptr + 1) << 8));
|
||||
} else
|
||||
#endif
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
val = ldw_u((u16 *) (ptr));
|
||||
#else
|
||||
val = *(u16 *) (ptr);
|
||||
#endif
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 2 -> %#x\n", addr, val);)
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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)
|
||||
{
|
||||
u32 val = 0;
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 4);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x3) {
|
||||
val = (*(u8 *) (ptr + 0) |
|
||||
(*(u8 *) (ptr + 1) << 8) |
|
||||
(*(u8 *) (ptr + 2) << 16) | (*(u8 *) (ptr + 3) << 24));
|
||||
} else
|
||||
#endif
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
val = ldl_u((u32 *) (ptr));
|
||||
#else
|
||||
val = *(u32 *) (ptr);
|
||||
#endif
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 4 -> %#x\n", addr, val);)
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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)
|
||||
{
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 1);
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 1 <- %#x\n", addr, val);)
|
||||
*(u8 *) (ptr) = 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)
|
||||
{
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 2);
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 2 <- %#x\n", addr, val);)
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
*(u8 *) (ptr + 0) = (val >> 0) & 0xff;
|
||||
*(u8 *) (ptr + 1) = (val >> 8) & 0xff;
|
||||
} else
|
||||
#endif
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
stw_u(val, (u16 *) (ptr));
|
||||
#else
|
||||
*(u16 *) (ptr) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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)
|
||||
{
|
||||
u8 *ptr;
|
||||
|
||||
ptr = mem_ptr(addr, 4);
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 4 <- %#x\n", addr, val);)
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
*(u8 *) (ptr + 0) = (val >> 0) & 0xff;
|
||||
*(u8 *) (ptr + 1) = (val >> 8) & 0xff;
|
||||
*(u8 *) (ptr + 2) = (val >> 16) & 0xff;
|
||||
*(u8 *) (ptr + 3) = (val >> 24) & 0xff;
|
||||
} else
|
||||
#endif
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
stl_u(val, (u32 *) (ptr));
|
||||
#else
|
||||
*(u32 *) (ptr) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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;*/
|
||||
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
return inb(addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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;*/
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
return inw(addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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;*/
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
return inl(addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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);)
|
||||
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
outb(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);)
|
||||
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
outw(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);)
|
||||
|
||||
if (ioperm(0x3c0, 0xdf, 1) == -1) {
|
||||
printk("Permission not set on port 0x%x.\n", addr);
|
||||
}
|
||||
outl(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;
|
||||
}
|
||||
|
||||
void X86EMU_setMemBase(void *base, size_t size)
|
||||
{
|
||||
M.mem_base = (int) base;
|
||||
M.mem_size = size;
|
||||
}
|
||||
|
||||
void X86EMU_setabseg(void *abseg)
|
||||
{
|
||||
M.abseg = (unsigned long) abseg;
|
||||
}
|
|
@ -0,0 +1,765 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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: Watcom C 10.6 or later
|
||||
* Environment: 32-bit DOS
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: Program to validate the x86 emulator library for
|
||||
* correctness. We run the emulator primitive operations
|
||||
* functions against the real x86 CPU, and compare the result
|
||||
* and flags to ensure correctness.
|
||||
*
|
||||
* We use inline assembler to compile and build this program.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "x86emu.h"
|
||||
#include "x86emu/prim_asm.h"
|
||||
|
||||
/*-------------------------- Implementation -------------------------------*/
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF)
|
||||
|
||||
#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \
|
||||
{ \
|
||||
parm_type d,s; \
|
||||
res_type r,r_asm; \
|
||||
ulong flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < dmax; d += dincr) { \
|
||||
for (s = 0; s < smax; s += sincr) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) {
|
||||
|
||||
#define VAL_TEST_BINARY(name) \
|
||||
r_asm = name##_asm(&flags,d,s); \
|
||||
r = name(d,s); \
|
||||
if (r != r_asm || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) {
|
||||
|
||||
#define VAL_TEST_BINARY_VOID(name) \
|
||||
name##_asm(&flags,d,s); \
|
||||
name(d,s); \
|
||||
r = r_asm = 0; \
|
||||
if (M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) {
|
||||
|
||||
#define VAL_FAIL_BYTE_BYTE_BINARY(name) \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
|
||||
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_FAIL_WORD_WORD_BINARY(name) \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
|
||||
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_FAIL_LONG_LONG_BINARY(name) \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_END_BINARY() \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_BYTE_BYTE_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_BYTE_BYTE_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_WORD_WORD_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_WORD_WORD_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_LONG_LONG_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_LONG_LONG_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_VOID_BYTE_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
|
||||
VAL_TEST_BINARY_VOID(name) \
|
||||
VAL_FAIL_BYTE_BYTE_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_VOID_WORD_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
|
||||
VAL_TEST_BINARY_VOID(name) \
|
||||
VAL_FAIL_WORD_WORD_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_VOID_LONG_BINARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
|
||||
VAL_TEST_BINARY_VOID(name) \
|
||||
VAL_FAIL_LONG_LONG_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_BYTE_ROTATE(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u8,u8,0xFF,8,1,1) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_BYTE_BYTE_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_WORD_ROTATE(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_WORD_WORD_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_LONG_ROTATE(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \
|
||||
VAL_TEST_BINARY(name) \
|
||||
VAL_FAIL_LONG_LONG_BINARY(name) \
|
||||
VAL_END_BINARY()
|
||||
|
||||
#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\
|
||||
{ \
|
||||
parm_type d,s; \
|
||||
res_type r,r_asm; \
|
||||
u8 shift; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < dmax; d += dincr) { \
|
||||
for (s = 0; s < smax; s += sincr) { \
|
||||
for (shift = 0; shift < maxshift; shift += 1) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) {
|
||||
|
||||
#define VAL_TEST_TERNARY(name) \
|
||||
r_asm = name##_asm(&flags,d,s,shift); \
|
||||
r = name(d,s,shift); \
|
||||
if (r != r_asm || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) {
|
||||
|
||||
#define VAL_FAIL_WORD_WORD_TERNARY(name) \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
|
||||
r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_FAIL_LONG_LONG_TERNARY(name) \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
|
||||
r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_END_TERNARY() \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_WORD_ROTATE_DBL(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \
|
||||
VAL_TEST_TERNARY(name) \
|
||||
VAL_FAIL_WORD_WORD_TERNARY(name) \
|
||||
VAL_END_TERNARY()
|
||||
|
||||
#define VAL_LONG_ROTATE_DBL(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \
|
||||
VAL_TEST_TERNARY(name) \
|
||||
VAL_FAIL_LONG_LONG_TERNARY(name) \
|
||||
VAL_END_TERNARY()
|
||||
|
||||
#define VAL_START_UNARY(parm_type,max,incr) \
|
||||
{ \
|
||||
parm_type d,r,r_asm; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < max; d += incr) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) {
|
||||
|
||||
#define VAL_TEST_UNARY(name) \
|
||||
r_asm = name##_asm(&flags,d); \
|
||||
r = name(d); \
|
||||
if (r != r_asm || M.x86.R_EFLG != flags) { \
|
||||
failed = true;
|
||||
|
||||
#define VAL_FAIL_BYTE_UNARY(name) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
|
||||
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_FAIL_WORD_UNARY(name) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
|
||||
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_FAIL_LONG_UNARY(name) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
|
||||
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
|
||||
|
||||
#define VAL_END_UNARY() \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_BYTE_UNARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_UNARY(u8,0xFF,0x1) \
|
||||
VAL_TEST_UNARY(name) \
|
||||
VAL_FAIL_BYTE_UNARY(name) \
|
||||
VAL_END_UNARY()
|
||||
|
||||
#define VAL_WORD_UNARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_UNARY(u16,0xFF00,0x100) \
|
||||
VAL_TEST_UNARY(name) \
|
||||
VAL_FAIL_WORD_UNARY(name) \
|
||||
VAL_END_UNARY()
|
||||
|
||||
#define VAL_WORD_BYTE_UNARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_UNARY(u16,0xFF,0x1) \
|
||||
VAL_TEST_UNARY(name) \
|
||||
VAL_FAIL_WORD_UNARY(name) \
|
||||
VAL_END_UNARY()
|
||||
|
||||
#define VAL_LONG_UNARY(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
VAL_START_UNARY(u32,0xFF000000,0x1000000) \
|
||||
VAL_TEST_UNARY(name) \
|
||||
VAL_FAIL_LONG_UNARY(name) \
|
||||
VAL_END_UNARY()
|
||||
|
||||
#define VAL_BYTE_MUL(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u8 d,s; \
|
||||
u16 r,r_asm; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF; d += 1) { \
|
||||
for (s = 0; s < 0xFF; s += 1) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
name##_asm(&flags,&r_asm,d,s); \
|
||||
M.x86.R_AL = d; \
|
||||
name(s); \
|
||||
r = M.x86.R_AX; \
|
||||
if (r != r_asm || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
|
||||
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
|
||||
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_WORD_MUL(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u16 d,s; \
|
||||
u16 r_lo,r_asm_lo; \
|
||||
u16 r_hi,r_asm_hi; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF00; d += 0x100) { \
|
||||
for (s = 0; s < 0xFF00; s += 0x100) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
|
||||
M.x86.R_AX = d; \
|
||||
name(s); \
|
||||
r_lo = M.x86.R_AX; \
|
||||
r_hi = M.x86.R_DX; \
|
||||
if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
|
||||
r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
|
||||
r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_LONG_MUL(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u32 d,s; \
|
||||
u32 r_lo,r_asm_lo; \
|
||||
u32 r_hi,r_asm_hi; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
|
||||
for (s = 0; s < 0xFF000000; s += 0x1000000) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
|
||||
M.x86.R_EAX = d; \
|
||||
name(s); \
|
||||
r_lo = M.x86.R_EAX; \
|
||||
r_hi = M.x86.R_EDX; \
|
||||
if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_BYTE_DIV(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u16 d,s; \
|
||||
u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF00; d += 0x100) { \
|
||||
for (s = 1; s < 0xFF; s += 1) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
M.x86.intr = 0; \
|
||||
M.x86.R_AX = d; \
|
||||
name(s); \
|
||||
r_quot = M.x86.R_AL; \
|
||||
r_rem = M.x86.R_AH; \
|
||||
if (M.x86.intr & INTR_SYNCH) \
|
||||
continue; \
|
||||
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \
|
||||
if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
|
||||
r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
|
||||
r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_WORD_DIV(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u32 d,s; \
|
||||
u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
|
||||
for (s = 0x100; s < 0xFF00; s += 0x100) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
M.x86.intr = 0; \
|
||||
M.x86.R_AX = d & 0xFFFF; \
|
||||
M.x86.R_DX = d >> 16; \
|
||||
name(s); \
|
||||
r_quot = M.x86.R_AX; \
|
||||
r_rem = M.x86.R_DX; \
|
||||
if (M.x86.intr & INTR_SYNCH) \
|
||||
continue; \
|
||||
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\
|
||||
if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
|
||||
r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
|
||||
r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
#define VAL_LONG_DIV(name) \
|
||||
printk("Validating %s ... ", #name); \
|
||||
{ \
|
||||
u32 d,s; \
|
||||
u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \
|
||||
u32 flags,inflags; \
|
||||
int f,failed = false; \
|
||||
char buf1[80],buf2[80]; \
|
||||
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
|
||||
for (s = 0x100; s < 0xFF00; s += 0x100) { \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags; \
|
||||
for (f = 0; f < 2; f++) { \
|
||||
M.x86.intr = 0; \
|
||||
M.x86.R_EAX = d; \
|
||||
M.x86.R_EDX = 0; \
|
||||
name(s); \
|
||||
r_quot = M.x86.R_EAX; \
|
||||
r_rem = M.x86.R_EDX; \
|
||||
if (M.x86.intr & INTR_SYNCH) \
|
||||
continue; \
|
||||
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \
|
||||
if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
|
||||
failed = true; \
|
||||
if (failed || trace) { \
|
||||
if (failed) \
|
||||
printk("fail\n"); \
|
||||
printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
|
||||
printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
|
||||
r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
|
||||
} \
|
||||
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (failed) \
|
||||
break; \
|
||||
} \
|
||||
if (!failed) \
|
||||
printk("passed\n"); \
|
||||
}
|
||||
|
||||
void printk(const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vfprintf(stdout, fmt, argptr);
|
||||
fflush(stdout);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
char *print_flags(char *buf, ulong flags)
|
||||
{
|
||||
char *separator = "";
|
||||
|
||||
buf[0] = 0;
|
||||
if (flags & F_CF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "CF");
|
||||
separator = ",";
|
||||
}
|
||||
if (flags & F_PF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "PF");
|
||||
separator = ",";
|
||||
}
|
||||
if (flags & F_AF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "AF");
|
||||
separator = ",";
|
||||
}
|
||||
if (flags & F_ZF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "ZF");
|
||||
separator = ",";
|
||||
}
|
||||
if (flags & F_SF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "SF");
|
||||
separator = ",";
|
||||
}
|
||||
if (flags & F_OF) {
|
||||
strcat(buf, separator);
|
||||
strcat(buf, "OF");
|
||||
separator = ",";
|
||||
}
|
||||
if (separator[0] == 0)
|
||||
strcpy(buf, "None");
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main(int argc)
|
||||
{
|
||||
ulong def_flags;
|
||||
int trace = false;
|
||||
|
||||
if (argc > 1)
|
||||
trace = true;
|
||||
memset(&M, 0, sizeof(M));
|
||||
def_flags = get_flags_asm() & ~ALL_FLAGS;
|
||||
|
||||
VAL_WORD_UNARY(aaa_word);
|
||||
VAL_WORD_UNARY(aas_word);
|
||||
|
||||
VAL_WORD_UNARY(aad_word);
|
||||
VAL_WORD_UNARY(aam_word);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(adc_byte);
|
||||
VAL_WORD_WORD_BINARY(adc_word);
|
||||
VAL_LONG_LONG_BINARY(adc_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(add_byte);
|
||||
VAL_WORD_WORD_BINARY(add_word);
|
||||
VAL_LONG_LONG_BINARY(add_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(and_byte);
|
||||
VAL_WORD_WORD_BINARY(and_word);
|
||||
VAL_LONG_LONG_BINARY(and_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(cmp_byte);
|
||||
VAL_WORD_WORD_BINARY(cmp_word);
|
||||
VAL_LONG_LONG_BINARY(cmp_long);
|
||||
|
||||
VAL_BYTE_UNARY(daa_byte);
|
||||
VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway)
|
||||
|
||||
VAL_BYTE_UNARY(dec_byte);
|
||||
VAL_WORD_UNARY(dec_word);
|
||||
VAL_LONG_UNARY(dec_long);
|
||||
|
||||
VAL_BYTE_UNARY(inc_byte);
|
||||
VAL_WORD_UNARY(inc_word);
|
||||
VAL_LONG_UNARY(inc_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(or_byte);
|
||||
VAL_WORD_WORD_BINARY(or_word);
|
||||
VAL_LONG_LONG_BINARY(or_long);
|
||||
|
||||
VAL_BYTE_UNARY(neg_byte);
|
||||
VAL_WORD_UNARY(neg_word);
|
||||
VAL_LONG_UNARY(neg_long);
|
||||
|
||||
VAL_BYTE_UNARY(not_byte);
|
||||
VAL_WORD_UNARY(not_word);
|
||||
VAL_LONG_UNARY(not_long);
|
||||
|
||||
VAL_BYTE_ROTATE(rcl_byte);
|
||||
VAL_WORD_ROTATE(rcl_word);
|
||||
VAL_LONG_ROTATE(rcl_long);
|
||||
|
||||
VAL_BYTE_ROTATE(rcr_byte);
|
||||
VAL_WORD_ROTATE(rcr_word);
|
||||
VAL_LONG_ROTATE(rcr_long);
|
||||
|
||||
VAL_BYTE_ROTATE(rol_byte);
|
||||
VAL_WORD_ROTATE(rol_word);
|
||||
VAL_LONG_ROTATE(rol_long);
|
||||
|
||||
VAL_BYTE_ROTATE(ror_byte);
|
||||
VAL_WORD_ROTATE(ror_word);
|
||||
VAL_LONG_ROTATE(ror_long);
|
||||
|
||||
VAL_BYTE_ROTATE(shl_byte);
|
||||
VAL_WORD_ROTATE(shl_word);
|
||||
VAL_LONG_ROTATE(shl_long);
|
||||
|
||||
VAL_BYTE_ROTATE(shr_byte);
|
||||
VAL_WORD_ROTATE(shr_word);
|
||||
VAL_LONG_ROTATE(shr_long);
|
||||
|
||||
VAL_BYTE_ROTATE(sar_byte);
|
||||
VAL_WORD_ROTATE(sar_word);
|
||||
VAL_LONG_ROTATE(sar_long);
|
||||
|
||||
VAL_WORD_ROTATE_DBL(shld_word);
|
||||
VAL_LONG_ROTATE_DBL(shld_long);
|
||||
|
||||
VAL_WORD_ROTATE_DBL(shrd_word);
|
||||
VAL_LONG_ROTATE_DBL(shrd_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(sbb_byte);
|
||||
VAL_WORD_WORD_BINARY(sbb_word);
|
||||
VAL_LONG_LONG_BINARY(sbb_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(sub_byte);
|
||||
VAL_WORD_WORD_BINARY(sub_word);
|
||||
VAL_LONG_LONG_BINARY(sub_long);
|
||||
|
||||
VAL_BYTE_BYTE_BINARY(xor_byte);
|
||||
VAL_WORD_WORD_BINARY(xor_word);
|
||||
VAL_LONG_LONG_BINARY(xor_long);
|
||||
|
||||
VAL_VOID_BYTE_BINARY(test_byte);
|
||||
VAL_VOID_WORD_BINARY(test_word);
|
||||
VAL_VOID_LONG_BINARY(test_long);
|
||||
|
||||
VAL_BYTE_MUL(imul_byte);
|
||||
VAL_WORD_MUL(imul_word);
|
||||
VAL_LONG_MUL(imul_long);
|
||||
|
||||
VAL_BYTE_MUL(mul_byte);
|
||||
VAL_WORD_MUL(mul_word);
|
||||
VAL_LONG_MUL(mul_long);
|
||||
|
||||
VAL_BYTE_DIV(idiv_byte);
|
||||
VAL_WORD_DIV(idiv_word);
|
||||
VAL_LONG_DIV(idiv_long);
|
||||
|
||||
VAL_BYTE_DIV(div_byte);
|
||||
VAL_WORD_DIV(div_word);
|
||||
VAL_LONG_DIV(div_long);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 debug definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/debug.h,v 1.4 2000/11/21 23:10:27 tsi Exp $ */
|
||||
|
||||
#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_IP_CS_F)
|
||||
|
||||
# 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 */
|
|
@ -0,0 +1,87 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_DECODE_H */
|
|
@ -0,0 +1,61 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 FPU instruction decoding.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_FPU_H
|
||||
#define __X86EMU_FPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
/* these have to be defined, whether 8087 support compiled in or not. */
|
||||
|
||||
extern void x86emuOp_esc_coprocess_d8 (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_d9 (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_da (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_db (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_dc (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_dd (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_de (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_df (u8 op1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_FPU_H */
|
|
@ -0,0 +1,45 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 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 */
|
|
@ -0,0 +1,971 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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: 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/prim_asm.h,v 1.3 2000/04/19 15:48:15 tsi Exp $ */
|
||||
|
||||
#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 */
|
|
@ -0,0 +1,231 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 primitive operation functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_PRIM_OPS_H
|
||||
#define __X86EMU_PRIM_OPS_H
|
||||
|
||||
#include "x86emu/prim_asm.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);
|
||||
|
||||
#if defined(__HAVE_INLINE_ASSEMBLER__) && !defined(PRIM_OPS_NO_REDEFINE_ASM)
|
||||
|
||||
#define aaa_word(d) aaa_word_asm(&M.x86.R_EFLG,d)
|
||||
#define aas_word(d) aas_word_asm(&M.x86.R_EFLG,d)
|
||||
#define aad_word(d) aad_word_asm(&M.x86.R_EFLG,d)
|
||||
#define aam_word(d) aam_word_asm(&M.x86.R_EFLG,d)
|
||||
#define adc_byte(d,s) adc_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define adc_word(d,s) adc_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define adc_long(d,s) adc_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define add_byte(d,s) add_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define add_word(d,s) add_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define add_long(d,s) add_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define and_byte(d,s) and_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define and_word(d,s) and_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define and_long(d,s) and_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define cmp_byte(d,s) cmp_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define cmp_word(d,s) cmp_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define cmp_long(d,s) cmp_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define daa_byte(d) daa_byte_asm(&M.x86.R_EFLG,d)
|
||||
#define das_byte(d) das_byte_asm(&M.x86.R_EFLG,d)
|
||||
#define dec_byte(d) dec_byte_asm(&M.x86.R_EFLG,d)
|
||||
#define dec_word(d) dec_word_asm(&M.x86.R_EFLG,d)
|
||||
#define dec_long(d) dec_long_asm(&M.x86.R_EFLG,d)
|
||||
#define inc_byte(d) inc_byte_asm(&M.x86.R_EFLG,d)
|
||||
#define inc_word(d) inc_word_asm(&M.x86.R_EFLG,d)
|
||||
#define inc_long(d) inc_long_asm(&M.x86.R_EFLG,d)
|
||||
#define or_byte(d,s) or_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define or_word(d,s) or_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define or_long(d,s) or_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define neg_byte(s) neg_byte_asm(&M.x86.R_EFLG,s)
|
||||
#define neg_word(s) neg_word_asm(&M.x86.R_EFLG,s)
|
||||
#define neg_long(s) neg_long_asm(&M.x86.R_EFLG,s)
|
||||
#define not_byte(s) not_byte_asm(&M.x86.R_EFLG,s)
|
||||
#define not_word(s) not_word_asm(&M.x86.R_EFLG,s)
|
||||
#define not_long(s) not_long_asm(&M.x86.R_EFLG,s)
|
||||
#define rcl_byte(d,s) rcl_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rcl_word(d,s) rcl_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rcl_long(d,s) rcl_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rcr_byte(d,s) rcr_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rcr_word(d,s) rcr_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rcr_long(d,s) rcr_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rol_byte(d,s) rol_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rol_word(d,s) rol_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define rol_long(d,s) rol_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define ror_byte(d,s) ror_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define ror_word(d,s) ror_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define ror_long(d,s) ror_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shl_byte(d,s) shl_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shl_word(d,s) shl_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shl_long(d,s) shl_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shr_byte(d,s) shr_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shr_word(d,s) shr_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shr_long(d,s) shr_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sar_byte(d,s) sar_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sar_word(d,s) sar_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sar_long(d,s) sar_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define shld_word(d,fill,s) shld_word_asm(&M.x86.R_EFLG,d,fill,s)
|
||||
#define shld_long(d,fill,s) shld_long_asm(&M.x86.R_EFLG,d,fill,s)
|
||||
#define shrd_word(d,fill,s) shrd_word_asm(&M.x86.R_EFLG,d,fill,s)
|
||||
#define shrd_long(d,fill,s) shrd_long_asm(&M.x86.R_EFLG,d,fill,s)
|
||||
#define sbb_byte(d,s) sbb_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sbb_word(d,s) sbb_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sbb_long(d,s) sbb_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sub_byte(d,s) sub_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sub_word(d,s) sub_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define sub_long(d,s) sub_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define test_byte(d,s) test_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define test_word(d,s) test_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define test_long(d,s) test_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define xor_byte(d,s) xor_byte_asm(&M.x86.R_EFLG,d,s)
|
||||
#define xor_word(d,s) xor_word_asm(&M.x86.R_EFLG,d,s)
|
||||
#define xor_long(d,s) xor_long_asm(&M.x86.R_EFLG,d,s)
|
||||
#define imul_byte(s) imul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s)
|
||||
#define imul_word(s) imul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s)
|
||||
#define imul_long(s) imul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s)
|
||||
#define imul_long_direct(res_lo,res_hi,d,s) imul_long_asm(&M.x86.R_EFLG,res_lo,res_hi,d,s)
|
||||
#define mul_byte(s) mul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s)
|
||||
#define mul_word(s) mul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s)
|
||||
#define mul_long(s) mul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s)
|
||||
#define idiv_byte(s) idiv_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s)
|
||||
#define idiv_word(s) idiv_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s)
|
||||
#define idiv_long(s) idiv_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s)
|
||||
#define div_byte(s) div_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s)
|
||||
#define div_word(s) div_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s)
|
||||
#define div_long(s) div_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_PRIM_OPS_H */
|
|
@ -0,0 +1,105 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 system specific functions. These functions
|
||||
* are always compiled and linked in the OS depedent libraries,
|
||||
* and never in a binary portable driver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/x86emui.h,v 1.4 2001/04/01 13:59:58 tsi Exp $ */
|
||||
|
||||
#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"
|
||||
#include "x86emu/fpu.h"
|
||||
#include "x86emu/fpu_regs.h"
|
||||
|
||||
#ifdef IN_MODULE
|
||||
#include <xf86_ansic.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
/*--------------------------- 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 */
|
Loading…
Reference in New Issue