l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../..
TARGET = src int10
include $(L4DIR)/mk/subdir.mk
int10: src

View File

@@ -0,0 +1,7 @@
x86emu reference:
git://anongit.freedesktop.org/xorg/xserver
e654de80ed560c480efc072d876808b1d78da052
Alternative?
https://github.com/wfeldt/libx86emu.git

View File

@@ -0,0 +1,12 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
TARGET = libx86emu_int10.a
SYSTEMS = x86-l4f amd64-l4f
SRC_CC = int10.cc
CFLAGS = -fomit-frame-pointer
DEFINES = -DUSE_IO
REQUIRES_LIBS = libio x86emu libedid
PC_FILENAME = x86emu_int10
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,741 @@
/**
* \file x86emu/lib/int10/int10.c(c)
* \brief Call VESA BIOS functions using the real mode interface
*
* \date 2005
* \author Frank Mehnert <fm3@os.inf.tu-dresden.de>
* Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* Alexander Warg <warg@os.inf.tu-dresden.de>
*/
/*
* (c) 2005-2009 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/sys/types.h>
#include <l4/sys/ipc.h>
#include <l4/sys/kdebug.h>
#include <l4/x86emu/x86emu.h>
#include <l4/re/env>
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/util/cap_alloc>
#include <l4/re/namespace>
#include <l4/re/dataspace>
#include <l4/util/mb_info.h>
#include <l4/sys/err.h>
#include <l4/io/io.h>
#include <l4/vbus/vbus.h>
#include <l4/vbus/vbus_types.h>
#include <l4/vbus/vbus_pci.h>
#include <l4/cxx/hlist>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <l4/x86emu/int10.h>
#include <l4/libedid/edid.h>
namespace {
struct ioport_res : public cxx::H_list_item
{
ioport_res(l4_uint16_t start, l4_uint16_t end)
: start(start), end(end)
{
_list.push_front(this);
}
unsigned short start, end;
bool warned;
typedef cxx::H_list_bss<ioport_res> List;
static List _list;
static bool port_is_avail(unsigned port, unsigned size);
};
ioport_res::List ioport_res::_list;
bool
ioport_res::port_is_avail(unsigned port, unsigned size)
{
for (List::Const_iterator i = _list.begin(); i != _list.end(); ++i)
if (i->start <= port && port + size - 1 <= i->end)
return true;
return false;
}
}
static void
port_request_cb(l4vbus_resource_t const *r)
{
new ioport_res(r->start, r->end);
}
enum {
Dbg_io = 0,
Dbg_mem = 0,
Dbg_pci = 0,
};
static l4_addr_t v_page[1024*1024/(L4_PAGESIZE)];
static l4_addr_t v_area;
static l4_umword_t initialized;
static L4::Cap<void> vbus;
static L4::Cap<L4Re::Dataspace> ds;
static l4vbus_device_handle_t root_bridge = L4VBUS_NULL;
static void
warn(u32 addr, const char *func)
{
printf("\033[31mWARNING: Function %s access %08lx\033[m\n", func,
(unsigned long)addr);
}
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
static int do_pcicfg(unsigned long addr, u32 *val32, int size, int out)
{
static l4_uint32_t config_reg;
/* check for PCI addr and data ports */
if (addr < 0xcf8 || addr >= 0xd00)
return 0;
if (addr == 0xcf8)
{
config_reg = *val32;
return 1;
}
if (addr >= 0xcfc)
{
l4_uint32_t reg;
l4_uint32_t v;
unsigned df = (config_reg >> 8) & 0xff;
unsigned bus = (config_reg >> 16) & 0xff;
df = (PCI_SLOT(df) << 16) | PCI_FUNC(df);
reg = (addr & 3) | (config_reg & 0xfc) | ((config_reg >> 16) & 0xf00);
if (Dbg_pci)
printf("CFG ACCESS(%d-%d): %02x:%03x.%02x reg=%x val=%p (*val=%lx)\n",
out, size, bus, (df >> 16) & 0xffff, df & 0xffff,
reg, val32, (unsigned long)*val32);
if (out)
l4vbus_pci_cfg_write(vbus.cap(), root_bridge, bus, df, reg,
*val32, size);
else
{
l4vbus_pci_cfg_read(vbus.cap(), root_bridge, bus, df, reg, &v, size);
*val32 = v;
}
}
else
printf("Uups: %lx\n", addr);
if (Dbg_pci)
printf("access to PCI %lx %s %lx\n", addr, out ? "WRITE" : "READ",
(unsigned long)*val32);
return 1;
}
static void
port_message(unsigned port, unsigned size, u32 value,
const char *insn_tag, const char *add_tag = "")
{
static char const *const ws[4] = { "b", "w", "X", "l" };
printf("%04x:%04x %s%s %x -> %lx%s\n", M.x86.R_CS, M.x86.R_IP,
insn_tag, ws[size - 1], port, (unsigned long)value, add_tag);
}
template< typename W >
static W X86API
port_in(X86EMU_pioAddr addr)
{
u32 r;
if (do_pcicfg(addr, &r, sizeof(W) * 8, 0))
return r;
if (!ioport_res::port_is_avail(addr, sizeof(W)))
{
port_message(addr, sizeof(W), r, "in", " ignored");
return 0;
}
switch (sizeof(W))
{
case 1: asm volatile ("in %w1, %b0" : "=a" (r) : "d" (addr)); break;
case 2: asm volatile ("in %w1, %w0" : "=a" (r) : "d" (addr)); break;
case 4: asm volatile ("in %w1, %0" : "=a" (r) : "d" (addr)); break;
default: r = 0;
}
if (Dbg_io)
port_message(addr, sizeof(W), r, "in");
return r;
}
template< typename W >
static void X86API
port_out(X86EMU_pioAddr addr, W val)
{
u32 r = val;
if (do_pcicfg(addr, &r, sizeof(W) * 8, 1))
return;
if (!ioport_res::port_is_avail(addr, sizeof(W)))
{
port_message(addr, sizeof(W), r, "out", " ignored");
return;
}
if (Dbg_io)
port_message(addr, sizeof(W), r, "out");
switch (sizeof(W))
{
case 1: asm volatile ("out %b0, %w1" : : "a" (r), "d" (addr)); break;
case 2: asm volatile ("out %w0, %w1" : : "a" (r), "d" (addr)); break;
case 4: asm volatile ("out %0, %w1" : : "a" (r), "d" (addr)); break;
default: break;
}
}
template< typename W >
static W X86API
mem_read(u32 addr)
{
if (addr > (1 << 20))
warn(addr, __FUNCTION__);
if (Dbg_mem)
printf("read(%d) %08x => ", (int)sizeof(W), (unsigned)addr);
W const *a = (W const *)(v_page[addr/L4_PAGESIZE] + (addr % L4_PAGESIZE));
if (Dbg_mem)
printf("%0*x\n", (int)sizeof(W)*2, (unsigned)*a);
return *a;
}
template< typename W >
static void X86API
mem_write(u32 addr, W val)
{
if (addr > (1 << 20))
warn(addr, __FUNCTION__);
if (Dbg_mem)
printf("write(%d) %0*x => %08x\n", (int)sizeof(W), (int)sizeof(W)*2, (unsigned)val, (unsigned)addr);
W *a = (W *)(v_page[addr/L4_PAGESIZE] + (addr % L4_PAGESIZE));
*a = val;
}
X86EMU_pioFuncs my_pioFuncs =
{
port_in<u8>, port_in<u16>, port_in<u32>,
port_out<u8>, port_out<u16>, port_out<u32>
};
X86EMU_memFuncs my_memFuncs =
{
mem_read<u8>, mem_read<u16>, mem_read<u32>,
mem_write<u8>, mem_write<u16>, mem_write<u32>
};
void
printk(const char *format, ...)
{
va_list list;
va_start(list, format);
vprintf(format, list);
va_end(list);
}
/* VESA access functions start here */
enum Function
{
VBE_get_info = 0x4f00,
VBE_get_mode_info = 0x4f01,
VBE_set_mode = 0x4f02,
VBE_set_base_addr = 0x4f07,
VBE_power = 0x4f10,
VBE_ddc = 0x4f15,
};
static int
x86emu_int10_init(void)
{
int error;
l4_addr_t addr;
l4_uint32_t idx;
if (initialized)
return 0;
int err;
vbus = L4Re::Env::env()->get_cap<void>("vbus");
if (!vbus.is_valid())
{
printf("no 'vbus' found in namespace\n");
return -L4_ENOENT;
}
err = l4vbus_get_device_by_hid(vbus.cap(), 0, &root_bridge, "PNP0A03", 0, 0);
if (err < 0)
{
printf("No PCI root bridge found: %d\n", err);
L4Re::Util::cap_alloc.free(vbus);
return -L4_ENOENT;
}
X86EMU_setupPioFuncs(&my_pioFuncs);
X86EMU_setupMemFuncs(&my_memFuncs);
M.x86.debug = 0 /*| DEBUG_DECODE_F*/;
l4io_request_all_ioports(port_request_cb);
/* Reserve region for physical memory 0x00000...0xfffff. Make sure that we
* can unmap it using one single l4_fpage_unmap (alignment). */
v_page[0] = 0;
if ((error = L4Re::Env::env()->rm()->reserve_area(&v_page[0], 1 << 20,
L4Re::Rm::F::Search_addr, 20)))
{
printf("Error %d reserving area for x86emu\n", error);
return error;
}
v_area = v_page[0];
/* Map physical page 0x00000 */
if (l4io_request_iomem_region(0, v_page[0], L4_PAGESIZE,
L4IO_MEM_CACHED | L4IO_MEM_USE_RESERVED_AREA) < 0)
{
printf("Error %d allocating physical page 0 for x86emu\n", error);
return error;
}
ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!ds.is_valid())
return -L4_ENOMEM;
if ((error = L4Re::Env::env()->mem_alloc()->alloc(L4_PAGESIZE, ds, 0)))
{
printf("Error %d allocating page for x86emu\n", error);
return error;
}
/* Map dummy as physical page 0x01000 */
v_page[1] = v_page[0] + L4_PAGESIZE;
if ((error = L4Re::Env::env()->rm()->attach((void **)&v_page[1], L4_PAGESIZE,
L4Re::Rm::F::In_area | L4Re::Rm::F::RW, ds,
0, L4_PAGESHIFT)))
{
printf("Error %d attaching page for x86emu\n", error);
return error;
}
for (idx = 0x09F000 / L4_PAGESIZE, addr = 0x09F000;
addr < 0x100000;
idx++, addr += L4_PAGESIZE)
v_page[idx] = v_page[0] + addr;
if ((error = l4io_request_iomem_region(0x09F000, v_page[0x9f],
0x100000 - 0x09F000,
L4IO_MEM_CACHED |
L4IO_MEM_USE_RESERVED_AREA)) < 0)
{
printf("BIOS area mapping failed: %x\n", error);
return error;
}
/* int 10 ; ret */
*(l4_uint8_t *)(v_page[1] + 0) = 0xcd;
*(l4_uint8_t *)(v_page[1] + 1) = 0x10;
*(l4_uint8_t *)(v_page[1] + 2) = 0xf4;
initialized = 1;
return 0;
}
static void setup_int10_entry(l4_uint16_t function)
{
M.x86.R_EAX = function;
M.x86.R_IP = 0; /* address of "int10; hlt" */
M.x86.R_SP = L4_PAGESIZE; /* SS:SP pointer to stack */
M.x86.R_CS =
M.x86.R_DS =
M.x86.R_ES =
M.x86.R_SS = L4_PAGESIZE >> 4;
}
static bool exec_int10()
{
X86EMU_exec();
return M.x86.R_AX == 0x004F;
}
int
x86emu_int10_done(void)
{
int ret;
unsigned i = 0;
if (!initialized)
return 0;
for (; i < sizeof(v_page) / sizeof(v_page[0]); ++i)
if (v_page[i])
L4Re::Env::env()->rm()->detach((void *)v_page[i], 0);
/* Free the area */
ret = L4Re::Env::env()->rm()->free_area(v_area);
initialized = 0;
return ret;
}
static int
far_to_addr(l4_uint32_t farp, l4_addr_t *addr)
{
int error;
l4_addr_t p = (farp & 0x0FFFF) + ((farp >> 12) & 0xFFFF0);
l4_addr_t idx = p / L4_PAGESIZE;
if (!v_page[idx])
{
v_page[idx] = v_page[0] + idx * L4_PAGESIZE;
error =
L4Re::Env::env()->rm()->attach((void **)&v_page[idx], L4_PAGESIZE,
L4Re::Rm::F::In_area | L4Re::Rm::F::RW,
ds, 0, L4_PAGESHIFT);
if (error)
{
printf("Error %d attaching page %li for x86emu\n", error, idx);
return error;
}
}
*addr = (l4_addr_t)(v_page[idx] + (p % L4_PAGESIZE));
return 0;
}
static void dump_mode(int mode, l4util_mb_vbe_mode_t *m)
{
char s[16];
if (!m)
{
printf("Mode: 0x%x: No information available\n", mode);
return;
}
snprintf(s, sizeof(s), "%dx%d@%d",
m->x_resolution, m->y_resolution, m->bits_per_pixel);
s[sizeof(s) - 1] = 0;
printf("Mode: 0x%x %13s, RGB: %d(%d):%d(%d):%d(%d) mode: %x\n",
mode, s,
m->red_field_position, m->red_mask_size,
m->green_field_position, m->green_mask_size,
m->blue_field_position, m->blue_mask_size,
m->mode_attributes);
}
static
l4util_mb_vbe_mode_t *get_mode_info(int mode)
{
setup_int10_entry(VBE_get_mode_info);
M.x86.R_ECX = mode; /* VESA mode */
M.x86.R_EDI = 0x800; /* ES:DI pointer to at least 256 bytes */
if (!exec_int10())
return 0;
l4util_mb_vbe_mode_t *m = (l4util_mb_vbe_mode_t *)(v_page[1] + 0x800);
if ((m->mode_attributes & 0x91) == 0x91)
return m;
return 0;
}
static int
x86emu_int10_read_ddc(unsigned *xres, unsigned *yres)
{
int error;
if ((error = x86emu_int10_init()))
return error;
printf("Trying to read DDC info\n");
// test whether DDC function is supported
setup_int10_entry(VBE_ddc);
M.x86.R_EBX = 0;
M.x86.R_ECX = 0;
if (!exec_int10())
{
printf("DDC function not supported\n");
return -L4_ENODEV;
}
printf("DDC level supported: 0x%x, screen blanked: %d\n",
M.x86.R_EBX & 0x3, M.x86.R_EBX & 0x4);
printf("Read EDID data\n");
// read EDID data block
setup_int10_entry(VBE_ddc);
M.x86.R_EBX = 1; // read EDID
M.x86.R_ECX = 0; // controller number, 0 = primary controller
M.x86.R_EDX = 0; // EDID block number
M.x86.R_EDI = 0x100; // ES.DI: pointer to 128 byte block where EDID block shall be returned
if (!exec_int10())
{
printf("EDID call failed 0x%x\n", M.x86.R_AX);
return -L4_EINVAL;
}
const unsigned char *edid = (const unsigned char *)(v_page[1] + 0x100);
printf("EDID Version %u.%u\n", libedid_version(edid), libedid_revision(edid));
printf(" %u extension blocks\n", libedid_num_ext_blocks(edid));
// dump EDID block (debugging)
if (1)
libedid_dump(edid);
// read manufacturer ID
unsigned char id[4];
libedid_pnp_id(edid, id);
printf("PNP ID=%s\n", id);
libedid_prefered_resolution(edid, xres, yres);
printf("Prefered mode: %ux%u\n", *xres, *yres);
return 0;
}
static
bool is_better_than(l4util_mb_vbe_mode_t *best, l4util_mb_vbe_mode_t *mode)
{
if (best->x_resolution == 0)
return true;
// the bigger the better
if ( mode->x_resolution > best->x_resolution
|| mode->y_resolution > best->y_resolution)
return true;
if ( mode->x_resolution < best->x_resolution
|| mode->y_resolution < best->y_resolution)
return false;
// prefer 16bit
return mode->bits_per_pixel == 16;
}
int
x86emu_int10_set_vbemode(int mode, l4util_mb_vbe_ctrl_t *ctrl_info,
l4util_mb_vbe_mode_t *mode_info)
{
int error;
l4_addr_t addr;
if ((error = x86emu_int10_init()))
return error;
printf("Trying execution of ``set VBE mode'' using x86emu\n");
/* Get VESA BIOS controller information. */
setup_int10_entry(VBE_get_info);
/*
* Store the "VBE2" signature into the info structure in order to get
* proper mode information.
*
* The presence of the signature, although no longer checked by many recent
* BIOS implementations, indicates that the size of the info structure is
* 512 bytes (instead of 256 bytes) and that VBE 3.0 modes (potentially
* non-standard) should be included in the mode list.
*/
*(l4_uint32_t *)(v_page[1] + 0x100) = 0x32454256U;
M.x86.R_EDI = 0x100; /* ES:DI pointer to at least 512 bytes */
if (!exec_int10())
{
printf("VBE BIOS not present.\n");
return -L4_EINVAL;
}
*ctrl_info = *(l4util_mb_vbe_ctrl_t *)(v_page[1] + 0x100);
if ((error = far_to_addr(ctrl_info->oem_string, &addr)))
return error;
const char *oem_string = (const char *)(addr);
printf("Found VESA BIOS version %d.%d\n"
"OEM %s\n",
(int)(ctrl_info->version >> 8),
(int)(ctrl_info->version & 0xFF),
ctrl_info->oem_string ? oem_string : "[unknown]");
if (ctrl_info->version < 0x0200)
{
printf("VESA BIOS 2.0 or later required.\n");
return -L4_EINVAL;
}
if (mode == ~0)
{
// mode == ~0 means to look for the 'best' mode available, we'll look
// for the highest 16bit mode
int max_val = 0;
int res;
unsigned pref_x = 0, pref_y = 0;
l4_uint32_t vmp = ctrl_info->video_mode;
for (;;)
{
if ((error = far_to_addr(vmp, &addr)))
return error;
l4_uint16_t *mode_entry = (l4_uint16_t *)addr;
if (*mode_entry == 0xffff)
break;
vmp += sizeof(l4_uint16_t);
}
l4_uint16_t *vid_modes = (l4_uint16_t *)malloc(vmp - ctrl_info->video_mode);
if ((error = far_to_addr(ctrl_info->video_mode, &addr)))
return error;
l4_uint16_t *mode_entry = (l4_uint16_t *)addr;
unsigned num_modes = 0;
for (; *mode_entry != 0xffff; ++mode_entry)
vid_modes[num_modes++] = *mode_entry;
printf("Scanning for 'best' possible mode:\n");
if ((res = x86emu_int10_read_ddc(&pref_x, &pref_y)) < 0)
printf("EDID not available (%d), finding best possible mode ...\n", res);
l4util_mb_vbe_mode_t best_mode;
best_mode.x_resolution = 0;
for (unsigned idx = 0; idx < num_modes; ++idx)
{
l4util_mb_vbe_mode_t *m = get_mode_info(vid_modes[idx]);
if (!m)
continue;
dump_mode(vid_modes[idx], m);
if (pref_x > 0)
{
if ( m->x_resolution <= pref_x && m->y_resolution <= pref_y
&& is_better_than(&best_mode, m))
{
best_mode = *m;
mode = vid_modes[idx];
}
}
else if (m->x_resolution > max_val && m->bits_per_pixel == 16)
{
max_val = m->x_resolution;
mode = vid_modes[idx];
best_mode = *m;
}
}
free(vid_modes);
if (mode == ~0)
{
printf("Could not find suitable mode\n");
return -L4_EINVAL;
}
printf("Chosen mode:\n");
dump_mode(mode, get_mode_info(mode));
printf("To force a specific setting use a '-m <mode>' option.\n");
*mode_info = best_mode;
}
else
{
l4util_mb_vbe_mode_t *mi = get_mode_info(mode);
if (!mi)
{
printf("Mode %x not supported\n", mode);
printf("List of supported graphics modes:\n");
l4_uint32_t video_mode_ptr = ctrl_info->video_mode;
for (;;)
{
if ((error = far_to_addr(video_mode_ptr, &addr)))
return error;
l4_uint16_t *mode_entry = (l4_uint16_t *)(addr);
if (*mode_entry == 0xffff)
break;
video_mode_ptr += sizeof(l4_uint16_t);
dump_mode(*mode_entry, get_mode_info(*mode_entry));
}
return -L4_EINVAL;
}
*mode_info = *mi;
}
/* Switch mode. */
setup_int10_entry(VBE_set_mode);
M.x86.R_EBX = mode & 0xf7ff; /* VESA mode; use current refresh rate */
M.x86.R_EBX |= 1 << 14; /* use flat buffer model */
if (0)
M.x86.R_EBX |= 1 << 15; /* no screen clearing */
X86EMU_exec();
// error check missing ?
printf("VBE mode 0x%x successfully set.\n", mode);
return mode;
}
int
x86emu_int10_pan(unsigned *x, unsigned *y)
{
int error;
if ((error = x86emu_int10_init()))
return error;
printf("Trying execution of ``set display start'' using x86emu\n");
/* Get VESA BIOS controller information. */
setup_int10_entry(VBE_set_base_addr);
M.x86.R_BL = 0x00; /* set display start */
M.x86.R_CX = *x; /* first displayed pixel in scanline */
M.x86.R_DX = *y; /* first displayed scanline */
if (!exec_int10())
{
printf("Panning to %d,%d not supported\n", *x, *y);
return -L4_EINVAL;
}
printf("Successful.\n");
return 0;
}

View File

@@ -0,0 +1,17 @@
License information
-------------------
The x86emu library is under a BSD style license, comaptible
with the XFree86 1.0 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 1.0 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.

View File

@@ -0,0 +1,18 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
TARGET = libx86emu.a
SYSTEMS = x86-l4f amd64-l4f
SRC_C = decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
CPPFLAGS = -DNO_LONG_LONG
CFLAGS = -fomit-frame-pointer
PRIVATE_INCDIR = $(PKGDIR)/lib/src
WARNINGS = -Wall -Wstrict-prototypes
DEBUG = 0
ifeq ($(DEBUG),1)
SRC_C += debug.c
endif
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,487 @@
/****************************************************************************
*
* 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.
*
****************************************************************************/
#include "x86emu/x86emui.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifndef NO_SYS_HEADERS
#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(const char *x, ...)
{
va_list ap;
char temp[100];
va_start(ap, x);
vsnprintf(temp, sizeof(temp), x, ap);
va_end(ap);
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;
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;
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("-");
(void)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':
M.x86.debug |= DEBUG_EXIT;
return;
case 'P':
noDecode = (noDecode) ? 0 : 1;
printk("Toggled decoding to %s\n", (noDecode) ? "FALSE" : "TRUE");
break;
case 't':
case 0:
done = 1;
break;
}
}
}
int
X86EMU_trace_on(void)
{
return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
}
int
X86EMU_trace_off(void)
{
return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
}
static int
parse_line(char *s, int *ps, int *n)
{
int cmd;
*n = 0;
while (*s == ' ' || *s == '\t')
s++;
ps[*n] = *s;
switch (*s) {
case '\n':
*n += 1;
return 0;
default:
cmd = *s;
*n += 1;
}
while (1) {
while (*s != ' ' && *s != '\t' && *s != '\n')
s++;
if (*s == '\n')
return cmd;
while (*s == ' ' || *s == '\t')
s++;
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");
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include <flux/x86/pc/direct_cons.h>
char *fgets(char *str, int size, FILE *stream);
char
*fgets(char *str, int size, FILE *stream)
{
int i;
int c;
if (size <= 0)
return NULL;
i = 0;
while (i < size)
{
c = direct_cons_getchar();
if (c == '\r')
{
putchar('\n');
putchar('\r');
if (i == 0)
{
str[0] = '\n';
str[1] = '\0';
return NULL;
}
break;
}
else if (c == 8)
{
if (i>0)
{
putchar(c);
putchar(' ');
putchar(c);
i--;
}
}
else
{
putchar(c);
str[i++] = c;
}
}
if (++i < size)
str[i] = '\n';
if (i < size)
str[i] = '\0';
return str;
}

View File

@@ -0,0 +1,976 @@
/****************************************************************************
*
* 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 const 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 const 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 = 0;
u8 stkelem = 0;
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;
}
}
}
#else
(void) destoffset;
(void) stkelem;
#endif /* X86EMU_FPU_PRESENT */
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
u8 stkelem = 0;
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;
}
}
#else
(void) destoffset;
(void) stkelem;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
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;
}
}
#else
(void) destoffset;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
u8 stkelem = 0;
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;
}
}
#else
(void) destoffset;
(void) stkelem;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
u8 stkelem = 0;
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;
}
}
#else
(void) destoffset;
(void) stkelem;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
u8 stkelem = 0;
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;
}
}
#else
(void) destoffset;
(void) stkelem;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static const 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 = 0;
u8 stkelem = 0;
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;
}
}
#else
(void) destoffset;
(void) stkelem;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
#include <stdarg.h>
#include <stdio.h>
void
printk(const char *format,...)
{
va_list list;
va_start(list, format);
vprintf(format, list);
va_end(list);
}

View File

@@ -0,0 +1,550 @@
/****************************************************************************
*
* 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 overridden by the
* user library.
*
****************************************************************************/
#include <l4/x86emu/x86emu.h>
#include "x86emu/x86emui.h"
#include <l4/x86emu/regs.h>
#include "x86emu/debug.h"
#include "x86emu/prim_ops.h"
#ifndef NO_SYS_HEADERS
#include <string.h>
#endif
#ifdef __GNUC__
/* Define some packed structures to use with unaligned accesses */
struct __una_u64 {
u64 x __attribute__ ((packed));
};
struct __una_u32 {
u32 x __attribute__ ((packed));
};
struct __una_u16 {
u16 x __attribute__ ((packed));
};
/* Elemental unaligned loads */
static __inline__ u64
ldq_u(u64 * p)
{
const struct __una_u64 *ptr = (const struct __una_u64 *) p;
return ptr->x;
}
static __inline__ u32
ldl_u(u32 * p)
{
const struct __una_u32 *ptr = (const struct __una_u32 *) p;
return ptr->x;
}
static __inline__ u16
ldw_u(u16 * p)
{
const struct __una_u16 *ptr = (const struct __una_u16 *) p;
return ptr->x;
}
/* Elemental unaligned stores */
static __inline__ void
stq_u(u64 val, u64 * p)
{
struct __una_u64 *ptr = (struct __una_u64 *) p;
ptr->x = val;
}
static __inline__ void
stl_u(u32 val, u32 * p)
{
struct __una_u32 *ptr = (struct __una_u32 *) p;
ptr->x = val;
}
static __inline__ void
stw_u(u16 val, u16 * p)
{
struct __una_u16 *ptr = (struct __una_u16 *) p;
ptr->x = val;
}
#else /* !__GNUC__ */
static __inline__ u64
ldq_u(u64 * p)
{
u64 ret;
memmove(&ret, p, sizeof(*p));
return ret;
}
static __inline__ u32
ldl_u(u32 * p)
{
u32 ret;
memmove(&ret, p, sizeof(*p));
return ret;
}
static __inline__ u16
ldw_u(u16 * p)
{
u16 ret;
memmove(&ret, p, sizeof(*p));
return ret;
}
static __inline__ void
stq_u(u64 val, u64 * p)
{
u64 tmp = val;
memmove(p, &tmp, sizeof(*p));
}
static __inline__ void
stl_u(u32 val, u32 * p)
{
u32 tmp = val;
memmove(p, &tmp, sizeof(*p));
}
static __inline__ void
stw_u(u16 val, u16 * p)
{
u16 tmp = val;
memmove(p, &tmp, sizeof(*p));
}
#endif /* __GNUC__ */
/*------------------------- Global Variables ------------------------------*/
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
X86EMU_intrFuncs _X86EMU_intrTab[256];
/*----------------------------- Implementation ----------------------------*/
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Byte value read from emulator memory.
REMARKS:
Reads a byte value from the emulator memory.
****************************************************************************/
u8 X86API
rdb(u32 addr)
{
u8 val;
if (addr > M.mem_size - 1) {
DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
)
HALT_SYS();
}
val = *(u8 *) (M.mem_base + addr);
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;
if (addr > M.mem_size - 2) {
DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
)
HALT_SYS();
}
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
val = (*(u8 *) (M.mem_base + addr) |
(*(u8 *) (M.mem_base + addr + 1) << 8));
}
else
#endif
val = ldw_u((u16 *) (M.mem_base + addr));
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;
if (addr > M.mem_size - 4) {
DB(printk("mem_read: address %#" PRIx32 " out of range!\n", addr);
)
HALT_SYS();
}
#ifdef __BIG_ENDIAN__
if (addr & 0x3) {
val = (*(u8 *) (M.mem_base + addr + 0) |
(*(u8 *) (M.mem_base + addr + 1) << 8) |
(*(u8 *) (M.mem_base + addr + 2) << 16) |
(*(u8 *) (M.mem_base + addr + 3) << 24));
}
else
#endif
val = ldl_u((u32 *) (M.mem_base + addr));
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)
{
DB(if (DEBUG_MEM_TRACE())
printk("%#08x 1 <- %#x\n", addr, val);)
if (addr > M.mem_size - 1) {
DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
)
HALT_SYS();
}
*(u8 *) (M.mem_base + addr) = 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)
{
DB(if (DEBUG_MEM_TRACE())
printk("%#08x 2 <- %#x\n", addr, val);)
if (addr > M.mem_size - 2) {
DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
)
HALT_SYS();
}
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
*(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
*(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
}
else
#endif
stw_u(val, (u16 *) (M.mem_base + addr));
}
/****************************************************************************
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)
{
DB(if (DEBUG_MEM_TRACE())
printk("%#08x 4 <- %#x\n", addr, val);)
if (addr > M.mem_size - 4) {
DB(printk("mem_write: address %#" PRIx32 " out of range!\n",addr);
)
HALT_SYS();
}
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
*(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff;
*(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff;
*(u8 *) (M.mem_base + addr + 2) = (val >> 16) & 0xff;
*(u8 *) (M.mem_base + addr + 3) = (val >> 24) & 0xff;
}
else
#endif
stl_u(val, (u32 *) (M.mem_base + addr));
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO byte read function. Doesn't perform real inb.
****************************************************************************/
static u8 X86API
p_inb(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inb %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO word read function. Doesn't perform real inw.
****************************************************************************/
static u16 X86API
p_inw(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inw %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO long read function. Doesn't perform real inl.
****************************************************************************/
static u32 X86API
p_inl(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inl %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO byte write function. Doesn't perform real outb.
****************************************************************************/
static void X86API
p_outb(X86EMU_pioAddr addr, u8 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outb %#02x -> %#04x \n", val, addr);)
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO word write function. Doesn't perform real outw.
****************************************************************************/
static void X86API
p_outw(X86EMU_pioAddr addr, u16 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outw %#04x -> %#04x \n", val, addr);)
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO ;ong write function. Doesn't perform real outl.
****************************************************************************/
static void X86API
p_outl(X86EMU_pioAddr addr, u32 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outl %#08x -> %#04x \n", val, addr);)
return;
}
/*------------------------- Global Variables ------------------------------*/
u8(X86APIP sys_rdb) (u32 addr) = rdb;
u16(X86APIP sys_rdw) (u32 addr) = rdw;
u32(X86APIP sys_rdl) (u32 addr) = rdl;
void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
/*----------------------------- Setup -------------------------------------*/
/****************************************************************************
PARAMETERS:
funcs - New memory function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
memory space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void
X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
{
sys_rdb = funcs->rdb;
sys_rdw = funcs->rdw;
sys_rdl = funcs->rdl;
sys_wrb = funcs->wrb;
sys_wrw = funcs->wrw;
sys_wrl = funcs->wrl;
}
/****************************************************************************
PARAMETERS:
funcs - New programmed I/O function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
I/O space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void
X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
{
sys_inb = funcs->inb;
sys_inw = funcs->inw;
sys_inl = funcs->inl;
sys_outb = funcs->outb;
sys_outw = funcs->outw;
sys_outl = funcs->outl;
}
/****************************************************************************
PARAMETERS:
funcs - New interrupt vector table to make active
REMARKS:
This function is used to set the pointers to functions which handle
interrupt processing in the emulator, allowing the user application to
hook interrupts as necessary for their application. Any interrupts that
are not hooked by the user application, and reflected and handled internally
in the emulator via the interrupt vector table. This allows the application
to get control when the code being emulated executes specific software
interrupts.
****************************************************************************/
void
X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
{
int i;
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = NULL;
if (funcs) {
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = funcs[i];
}
}
/****************************************************************************
PARAMETERS:
int - New software interrupt to prepare for
REMARKS:
This function is used to set up the emulator state to execute 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;
}

View File

@@ -0,0 +1,208 @@
/****************************************************************************
*
* 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.
*
****************************************************************************/
#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("%s",x)
#define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
x86emu_decode_printf(x,y)
/*
* The following allows us to look at the bytes of an instruction. The
* first INCR_INSTRN_LEN, is called every time 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(const char *x, ...) __attribute__((format(printf, 1, 2)));
extern void x86emu_just_disassemble(void);
extern void x86emu_single_step(void);
extern void x86emu_end_instr(void);
extern void x86emu_dump_regs(void);
extern void x86emu_dump_xregs(void);
extern void x86emu_print_int_vect(u16 iv);
extern void x86emu_instrument_instruction(void);
extern void x86emu_check_ip_access(void);
extern void x86emu_check_sp_access(void);
extern void x86emu_check_mem_access(u32 p);
extern void x86emu_check_data_access(uint s, uint o);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DEBUG_H */

View File

@@ -0,0 +1,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);
u32 decode_rm00_address(int rm);
u32 decode_rm01_address(int rm);
u32 decode_rm10_address(int rm);
u32 decode_sib_address(int sib, int mod);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DECODE_H */

View File

@@ -0,0 +1,60 @@
/****************************************************************************
*
* 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 */

View File

@@ -0,0 +1,119 @@
/****************************************************************************
*
* 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
#ifdef PACK
#pragma PACK
#endif
/* 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;
};
#ifdef END_PACK
#pragma END_PACK
#endif
/*
* 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 */

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/****************************************************************************
*
* 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
#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);
void cpuid(void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_PRIM_OPS_H */

View File

@@ -0,0 +1,77 @@
/****************************************************************************
*
* Inline helpers for x86emu
*
* Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
*
* ========================================================================
*
* 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: GNU C
* Environment: GCC on i386 or x86-64
* Developer: Bart Trojanowski
*
* Description: This file defines a few x86 macros that can be used by the
* emulator to execute native instructions.
*
* For PIC vs non-PIC code refer to:
* http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
*
****************************************************************************/
#ifndef __X86EMU_PRIM_X86_GCC_H
#define __X86EMU_PRIM_X86_GCC_H
#include <l4/x86emu/types.h>
#if !defined(__GNUC__) || !(defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__))
#error This file is intended to be used by gcc on i386 or x86-64 system
#endif
#if defined(__PIC__) && defined(__i386__)
#define X86EMU_HAS_HW_CPUID 1
static inline void
hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d)
{
__asm__ __volatile__("pushl %%ebx \n\t"
"cpuid \n\t"
"movl %%ebx, %1 \n\t"
"popl %%ebx \n\t":"=a"(*a), "=r"(*b),
"=c"(*c), "=d"(*d)
:"a"(*a), "c"(*c)
:"cc");
}
#else /* ! (__PIC__ && __i386__) */
#define x86EMU_HAS_HW_CPUID 1
static inline void
hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d)
{
__asm__ __volatile__("cpuid":"=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
:"a"(*a), "c"(*c)
:"cc");
}
#endif /* __PIC__ && __i386__ */
#endif /* __X86EMU_PRIM_X86_GCC_H */

View File

@@ -0,0 +1,110 @@
/****************************************************************************
*
* 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 dependent libraries,
* and never in a binary portable driver.
*
****************************************************************************/
#ifndef __X86EMU_X86EMUI_H
#define __X86EMU_X86EMUI_H
/* If we are compiling in C++ mode, we can compile some functions as
* inline to increase performance (however the code size increases quite
* dramatically in this case).
*/
#if defined(__cplusplus)
#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 <l4/x86emu/x86emu.h>
#include <l4/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"
#ifndef NO_SYS_HEADERS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* avoid conflicts with Solaris sys/regset.h */
# if defined(__sun) && defined(CS)
# undef CS
# undef DS
# undef SS
# undef ES
# undef FS
# undef GS
# endif
#endif /* NO_SYS_HEADERS */
/*--------------------------- 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 */