released 0.8.7 (new MMU layout, m5484LITE board working again)
This commit is contained in:
403
BaS_gcc/x86emu/x86biosemu.c
Normal file
403
BaS_gcc/x86emu/x86biosemu.c
Normal file
@@ -0,0 +1,403 @@
|
||||
#define RINFO_ONLY
|
||||
#include "x86debug.h"
|
||||
#include "radeonfb.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "util.h"
|
||||
#include "driver_mem.h"
|
||||
#include "x86emu.h"
|
||||
#include "pci.h"
|
||||
#include "pci_ids.h"
|
||||
|
||||
#define USE_SDRAM
|
||||
#define DIRECT_ACCESS
|
||||
|
||||
#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)
|
||||
|
||||
#define PCI_VGA_RAM_IMAGE_START 0xC0000
|
||||
#define PCI_RAM_IMAGE_START 0xD0000
|
||||
#define SYS_BIOS 0xF0000
|
||||
#define SIZE_EMU 0x100000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long ident;
|
||||
union
|
||||
{
|
||||
long l;
|
||||
short i[2];
|
||||
char c[4];
|
||||
} v;
|
||||
} COOKIE;
|
||||
|
||||
struct rom_header
|
||||
{
|
||||
uint16_t signature;
|
||||
uint8_t size;
|
||||
uint8_t init[3];
|
||||
uint8_t reserved[0x12];
|
||||
uint16_t data;
|
||||
};
|
||||
|
||||
struct pci_data
|
||||
{
|
||||
uint32_t signature;
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t reserved_1;
|
||||
uint16_t dlen;
|
||||
uint8_t drevision;
|
||||
uint8_t class_lo;
|
||||
uint16_t class_hi;
|
||||
uint16_t ilen;
|
||||
uint16_t irevision;
|
||||
uint8_t type;
|
||||
uint8_t indicator;
|
||||
uint16_t reserved_2;
|
||||
};
|
||||
|
||||
static struct radeonfb_info *rinfo_biosemu;
|
||||
uint16_t offset_port;
|
||||
uint32_t offset_mem;
|
||||
static uint32_t offset_io;
|
||||
static uint32_t config_address_reg;
|
||||
|
||||
extern int x86_pcibios_emulator();
|
||||
extern COOKIE *get_cookie(long id);
|
||||
extern short restart, os_magic;
|
||||
|
||||
X86EMU_sysEnv _X86EMU_env;
|
||||
|
||||
/* general software interrupt handler */
|
||||
uint32_t getIntVect(int num)
|
||||
{
|
||||
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
|
||||
}
|
||||
|
||||
/* FixME: There is already a push_word() in the emulator */
|
||||
void pushw(uint16_t val)
|
||||
{
|
||||
X86_ESP -= 2;
|
||||
MEM_WW(((uint32_t) X86_SS << 4) + X86_SP, val);
|
||||
}
|
||||
|
||||
int run_bios_int(int num)
|
||||
{
|
||||
uint32_t 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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
val = * (uint8_t *) (offset_io + (uint32_t) port);
|
||||
//dbg("%s: inb(0x%x) = 0x%x\r\n", __FUNCTION__, port, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t inw(uint16_t port)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
val = swpw(*(uint16_t *)(offset_io + (uint32_t) port));
|
||||
//dbg("inw(0x%x) = 0x%x\r\n", port, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t inl(uint16_t port)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
val = swpl(*(uint32_t *)(offset_io + (uint32_t) port));
|
||||
//dbg("0x%x) = 0x%x\r\n", port, val);
|
||||
}
|
||||
else if (port == 0xCF8)
|
||||
{
|
||||
val = config_address_reg;
|
||||
dbg("inl(0x%x) = 0x%x\r\n", port, val);
|
||||
}
|
||||
else if ((port == 0xCFC) && ((config_address_reg & 0x80000000) != 0))
|
||||
{
|
||||
dbg("%s: PCI BIOS access to register %x\r\n", __FUNCTION__, config_address_reg);
|
||||
switch (config_address_reg & 0xFC)
|
||||
{
|
||||
case PCIIDR:
|
||||
val = ((uint32_t) rinfo_biosemu->chipset << 16) + PCI_VENDOR_ID_ATI;
|
||||
break;
|
||||
|
||||
case PCIBAR1:
|
||||
val = (uint32_t) offset_port + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
val = pci_read_config_longword(rinfo_biosemu->handle, config_address_reg & 0xFC);
|
||||
break;
|
||||
}
|
||||
dbg("inl(0x%x) = 0x%x\r\n", port, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void outb(uint8_t val, uint16_t port)
|
||||
{
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
//dbg("outb(0x%x, 0x%x)\r\n", port, val);
|
||||
*(uint8_t *)(offset_io + (uint32_t) port) = val;
|
||||
}
|
||||
}
|
||||
|
||||
void outw(uint16_t val, uint16_t port)
|
||||
{
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
//dbg("outw(0x%x, 0x%x)\r\n", port, val);
|
||||
*(uint16_t *)(offset_io + (uint32_t) port) = swpw(val);
|
||||
}
|
||||
}
|
||||
|
||||
void outl(uint32_t val, uint16_t port)
|
||||
{
|
||||
if ((port >= offset_port) && (port <= offset_port + 0xFF))
|
||||
{
|
||||
//dbg("outl(0x%x, 0x%x)\r\n", port, val);
|
||||
*(uint32_t *)(offset_io + (uint32_t) port) = swpl(val);
|
||||
}
|
||||
else if (port == 0xCF8)
|
||||
{
|
||||
dbg("outl(0x%x, 0x%x)\r\n", port, val);
|
||||
config_address_reg = val;
|
||||
}
|
||||
else if ((port == 0xCFC) && ((config_address_reg & 0x80000000) !=0))
|
||||
{
|
||||
if ((config_address_reg & 0xFC) == PCIBAR1)
|
||||
offset_port = (uint16_t)val & 0xFFFC;
|
||||
else
|
||||
{
|
||||
dbg("outl(0x%x, 0x%x) to PCI config space\r\n", port, val);
|
||||
pci_write_config_longword(rinfo_biosemu->handle, config_address_reg & 0xFC, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Interrupt multiplexer */
|
||||
|
||||
void do_int(int num)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (num)
|
||||
{
|
||||
#ifndef _PC
|
||||
case 0x10:
|
||||
case 0x42:
|
||||
case 0x6D:
|
||||
if (getIntVect(num) == 0x0000)
|
||||
dbg("uninitialised int vector\r\n");
|
||||
if (getIntVect(num) == 0xFF065)
|
||||
{
|
||||
//ret = int42_handler();
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 0x15:
|
||||
//ret = int15_handler();
|
||||
ret = 1;
|
||||
break;
|
||||
case 0x16:
|
||||
//ret = int16_handler();
|
||||
ret = 0;
|
||||
break;
|
||||
case 0x1A:
|
||||
ret = x86_pcibios_emulator();
|
||||
ret = 1;
|
||||
break;
|
||||
case 0xe6:
|
||||
//ret = intE6_handler();
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!ret)
|
||||
ret = run_bios_int(num);
|
||||
}
|
||||
|
||||
static int setup_system_bios(void *base_addr)
|
||||
{
|
||||
char *base = (char *) base_addr;
|
||||
int i;
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
for(i = 0; i < SIZE_EMU + 4; base[i++] = 0xF4);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void run_bios(struct radeonfb_info *rinfo)
|
||||
{
|
||||
long i, j;
|
||||
unsigned char *ptr;
|
||||
struct rom_header *rom_header;
|
||||
struct pci_data *rom_data;
|
||||
unsigned long rom_size=0;
|
||||
unsigned long image_size=0;
|
||||
void *biosmem = (void *) 0x0100000; /* when run_bios() is called, SDRAM is valid but not added to the system */
|
||||
unsigned long addr;
|
||||
unsigned short initialcs;
|
||||
unsigned short initialip;
|
||||
unsigned short devfn = (unsigned short) rinfo->handle;
|
||||
X86EMU_intrFuncs intFuncs[256];
|
||||
|
||||
if ((rinfo->mmio_base == NULL) || (rinfo->io_base == NULL))
|
||||
{
|
||||
dbg("%s: rinfo->mmio_base = %p, rinfo->io_base = %p\r\n",
|
||||
__FUNCTION__, rinfo->mmio_base, rinfo->io_base);
|
||||
return;
|
||||
}
|
||||
|
||||
rinfo_biosemu = rinfo;
|
||||
config_address_reg = 0;
|
||||
offset_port = 0x300;
|
||||
offset_io = (uint32_t) rinfo->io_base - (uint32_t) offset_port;
|
||||
offset_mem = (uint32_t) rinfo->fb_base - 0xA0000;
|
||||
|
||||
rom_header = NULL;
|
||||
do
|
||||
{
|
||||
rom_header = (struct rom_header *) ((unsigned long) rom_header + image_size); // get next image
|
||||
rom_data = (struct pci_data *) ((unsigned long)rom_header + (unsigned long) BIOS_IN16((long) &rom_header->data));
|
||||
image_size = (unsigned long) BIOS_IN16((long) &rom_data->ilen) * 512;
|
||||
} while ((BIOS_IN8((long) &rom_data->type) != 0) && (BIOS_IN8((long) &rom_data->indicator) != 0)); // make sure we got x86 version
|
||||
|
||||
if (BIOS_IN8((long) &rom_data->type) != 0)
|
||||
{
|
||||
dbg("%s: ROM data type = 0x%x\r\n", __FUNCTION__, BIOS_IN8((long) &rom_data->type));
|
||||
return;
|
||||
}
|
||||
|
||||
rom_size = (unsigned long) BIOS_IN8((long) &rom_header->size) * 512;
|
||||
|
||||
if (PCI_CLASS_DISPLAY_VGA == BIOS_IN16((long) &rom_data->class_hi))
|
||||
{
|
||||
memset((char *) biosmem, 0, SIZE_EMU);
|
||||
setup_system_bios((char *) biosmem);
|
||||
|
||||
dbg("%s: Copying VGA ROM Image from %p to %p (0x%lx bytes)\r\n",
|
||||
__FUNCTION__, (long) rinfo->bios_seg + (long) rom_header,
|
||||
biosmem + PCI_VGA_RAM_IMAGE_START, rom_size);
|
||||
{
|
||||
long bytes_align = (long) rom_header & 3;
|
||||
|
||||
ptr = (unsigned char *) biosmem;
|
||||
i = (long) rom_header;
|
||||
j = PCI_VGA_RAM_IMAGE_START;
|
||||
|
||||
if (bytes_align)
|
||||
for(; i < 4 - bytes_align; ptr[j++] = BIOS_IN8(i++));
|
||||
|
||||
for(; i < (long) rom_header + rom_size; i += 4, j += 4)
|
||||
*((unsigned long *) &ptr[j]) = swpl(BIOS_IN32(i));
|
||||
}
|
||||
addr = PCI_VGA_RAM_IMAGE_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((char *) biosmem, 0, SIZE_EMU);
|
||||
setup_system_bios((char *) biosmem);
|
||||
|
||||
dbg("%s: Copying non-VGA ROM Image from %p to %p (0x%lx bytes)\r\n", __FUNCTION__,
|
||||
(long) rinfo->bios_seg + (long) rom_header,
|
||||
biosmem + PCI_RAM_IMAGE_START,
|
||||
rom_size);
|
||||
ptr = (unsigned char *) biosmem;
|
||||
for (i = (long) rom_header, j = PCI_RAM_IMAGE_START; i < (long) rom_header+rom_size; ptr[j++] = BIOS_IN8(i++));
|
||||
addr = PCI_RAM_IMAGE_START;
|
||||
}
|
||||
|
||||
initialcs = (addr & 0xF0000) >> 4;
|
||||
initialip = (addr + 3) & 0xFFFF;
|
||||
|
||||
X86EMU_setMemBase((void *) biosmem, SIZE_EMU);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intFuncs[i] = do_int;
|
||||
|
||||
X86EMU_setupIntrFuncs(intFuncs);
|
||||
{
|
||||
char *date = "01/01/99";
|
||||
for (i = 0; date[i]; i++)
|
||||
wrb(0xffff5 + i, date[i]);
|
||||
wrb(0xffff7, '/');
|
||||
wrb(0xffffa, '/');
|
||||
}
|
||||
{
|
||||
/* FixME: move PIT init to its own file */
|
||||
outb(0x36, 0x43);
|
||||
outb(0x00, 0x40);
|
||||
outb(0x00, 0x40);
|
||||
}
|
||||
// setup_int_vect();
|
||||
|
||||
/* cpu setup */
|
||||
X86_AX = devfn ? devfn : 0xff;
|
||||
X86_DX = 0x80;
|
||||
X86_EIP = initialip;
|
||||
X86_CS = initialcs;
|
||||
|
||||
/* Initialize stack and data segment */
|
||||
X86_SS = initialcs;
|
||||
X86_SP = 0xfffe;
|
||||
X86_DS = 0x0040;
|
||||
X86_ES = 0x0000;
|
||||
|
||||
/*
|
||||
* 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(0x10cd); /* int #0x10 */
|
||||
// pushw(0x0013); /* 320 x 200 x 256 colors */
|
||||
// // pushw(0x000F); /* 640 x 350 x mono */
|
||||
// pushw(0xb890); /* nop, mov ax,#0x13 */
|
||||
pushw(X86_SS);
|
||||
pushw(X86_SP + 2);
|
||||
#ifdef DBG_X86EMU
|
||||
X86EMU_trace_on();
|
||||
X86EMU_set_debug(DEBUG_DECODE_F | DEBUG_TRACE_F);
|
||||
#endif
|
||||
|
||||
dbg("%s: X86EMU entering emulator\r\n", __FUNCTION__);
|
||||
//*vblsem = 0;
|
||||
X86EMU_exec();
|
||||
//*vblsem = 1;
|
||||
dbg("%s: X86EMU halted\r\n", __FUNCTION__);
|
||||
// biosfn_set_video_mode(0x13); /* 320 x 200 x 256 colors */
|
||||
memset((char *) biosmem, 0, SIZE_EMU);
|
||||
}
|
||||
451
BaS_gcc/x86emu/x86debug.c
Normal file
451
BaS_gcc/x86emu/x86debug.c
Normal file
@@ -0,0 +1,451 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1991-2004 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file contains the code to handle debugging of the
|
||||
* emulator.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "bas_types.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "x86debug.h"
|
||||
#include "x86emui.h"
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
#ifdef DBG_X86EMU
|
||||
|
||||
static void print_encoded_bytes (uint16_t s, uint16_t 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())
|
||||
{
|
||||
xprintf("%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!
|
||||
*/
|
||||
xprintf("%x:%x ", M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_decoded_instruction();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void disassemble_forward (uint16_t seg, uint16_t 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)(((uint32_t)M.x86.R_CS<<4) + (M.x86.R_IP++));
|
||||
(x86emu_optab[op1])(op1);
|
||||
}
|
||||
/* end major hack mode. */
|
||||
}
|
||||
#endif
|
||||
|
||||
void x86emu_check_ip_access (void)
|
||||
{
|
||||
/* NULL as of now */
|
||||
}
|
||||
|
||||
void x86emu_check_sp_access (void)
|
||||
{
|
||||
}
|
||||
|
||||
void x86emu_check_mem_access(uint32_t dummy)
|
||||
{
|
||||
/* check bounds, etc */
|
||||
}
|
||||
|
||||
void x86emu_check_data_access(unsigned int dummy1, unsigned int 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 (uint16_t s, uint16_t 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));
|
||||
}
|
||||
xprintf("%-20s", buf1);
|
||||
}
|
||||
|
||||
static void print_decoded_instruction (void)
|
||||
{
|
||||
xprintf("%s", M.x86.decoded_buf);
|
||||
}
|
||||
|
||||
void x86emu_print_int_vect(uint16_t iv)
|
||||
{
|
||||
uint16_t seg,off;
|
||||
|
||||
if (iv > 256)
|
||||
return;
|
||||
|
||||
seg = fetch_data_word_abs(0, iv * 4);
|
||||
off = fetch_data_word_abs(0, iv *4 + 2);
|
||||
xprintf("%04x:%04x", seg, off);
|
||||
}
|
||||
|
||||
void X86EMU_dump_memory (uint16_t seg, uint16_t off, uint32_t amt)
|
||||
{
|
||||
uint32_t start = off & 0xfffffff0;
|
||||
uint32_t end = (off + 16) & 0xfffffff0;
|
||||
uint32_t i;
|
||||
uint32_t current;
|
||||
|
||||
current = start;
|
||||
while (end <= off + amt) {
|
||||
xprintf("%04x:%04x ", seg, start);
|
||||
|
||||
for (i = start; i < off; i++)
|
||||
xprintf(" ");
|
||||
for ( ; i< end; i++)
|
||||
xprintf("%02x", fetch_data_byte_abs(seg, i));
|
||||
xprintf("\r\n");
|
||||
start = end;
|
||||
end = start + 16;
|
||||
}
|
||||
}
|
||||
|
||||
void x86emu_single_step (void)
|
||||
{
|
||||
#if 0
|
||||
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) {
|
||||
DPRINT("-");
|
||||
p = fgets(s, 1023, stdin);
|
||||
cmd = parse_line(s, ps, &ntok);
|
||||
switch(cmd) {
|
||||
case 'u':
|
||||
disassemble_forward(M.x86.saved_cs,(uint16_t)offset,10);
|
||||
break;
|
||||
case 'd':
|
||||
if (ntok == 2) {
|
||||
segment = M.x86.saved_cs;
|
||||
offset = ps[1];
|
||||
X86EMU_dump_memory(segment,(uint16_t)offset,16);
|
||||
offset += 16;
|
||||
} else if (ntok == 3) {
|
||||
segment = ps[1];
|
||||
offset = ps[2];
|
||||
X86EMU_dump_memory(segment,(uint16_t)offset,16);
|
||||
offset += 16;
|
||||
} else {
|
||||
segment = M.x86.saved_cs;
|
||||
X86EMU_dump_memory(segment,(uint16_t)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;
|
||||
DPRINT("Toggled decoding to ");
|
||||
DPRINT((noDecode)?"FALSE":"TRUE");
|
||||
DPRINT("\r\n");
|
||||
break;
|
||||
case 't':
|
||||
case 0:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
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
|
||||
|
||||
#endif /* DBG_X86EMU */
|
||||
|
||||
void x86emu_dump_regs (void)
|
||||
{
|
||||
xprintf("\tAX=%04x", M.x86.R_AX);
|
||||
xprintf(" BX=%04x", M.x86.R_BX);
|
||||
xprintf(" CX=%04x", M.x86.R_CX);
|
||||
xprintf(" DX=%04x", M.x86.R_DX);
|
||||
xprintf(" SP=%04x", M.x86.R_SP);
|
||||
xprintf(" BP=%04x", M.x86.R_BP);
|
||||
xprintf(" SI=%04x", M.x86.R_SI);
|
||||
xprintf(" DI=%04x", M.x86.R_DI);
|
||||
xprintf("\r\n");
|
||||
xprintf("\tDS=%04x", M.x86.R_DS);
|
||||
xprintf(" ES=%04x", M.x86.R_ES);
|
||||
xprintf(" SS=%04x", M.x86.R_SS);
|
||||
xprintf(" CS=%04x", M.x86.R_CS);
|
||||
xprintf(" IP=%04x", M.x86.R_IP);
|
||||
if (ACCESS_FLAG(F_OF)) xprintf("OV "); /* CHECKED... */
|
||||
else xprintf("NV ");
|
||||
if (ACCESS_FLAG(F_DF)) xprintf("DN ");
|
||||
else xprintf("UP ");
|
||||
if (ACCESS_FLAG(F_IF)) xprintf("EI ");
|
||||
else xprintf("DI ");
|
||||
if (ACCESS_FLAG(F_SF)) xprintf("NG ");
|
||||
else xprintf("PL ");
|
||||
if (ACCESS_FLAG(F_ZF)) xprintf("ZR ");
|
||||
else xprintf("NZ ");
|
||||
if (ACCESS_FLAG(F_AF)) xprintf("AC ");
|
||||
else xprintf("NA ");
|
||||
if (ACCESS_FLAG(F_PF)) xprintf("PE ");
|
||||
else xprintf("PO ");
|
||||
if (ACCESS_FLAG(F_CF)) xprintf("CY ");
|
||||
else xprintf("NC ");
|
||||
xprintf("\r\n");
|
||||
}
|
||||
|
||||
void x86emu_dump_xregs (void)
|
||||
{
|
||||
xprintf(" EAX=%08x", M.x86.R_EAX );
|
||||
xprintf(" EBX=%08x", M.x86.R_EBX );
|
||||
xprintf(" ECX=%08x", M.x86.R_ECX );
|
||||
xprintf(" EDX=%08x", M.x86.R_EDX );
|
||||
xprintf("\r\n");
|
||||
xprintf(" ESP=%08x", M.x86.R_ESP );
|
||||
xprintf(" EBP=%08x", M.x86.R_EBP );
|
||||
xprintf(" ESI=%08x", M.x86.R_ESI );
|
||||
xprintf(" EDI=%08x", M.x86.R_EDI );
|
||||
xprintf("\r\n");
|
||||
xprintf(" DS=%08x", M.x86.R_DS );
|
||||
xprintf(" ES=%08x", M.x86.R_ES );
|
||||
xprintf(" SS=%08x", M.x86.R_SS );
|
||||
xprintf(" CS=%08x", M.x86.R_CS );
|
||||
xprintf(" EIP%08x=", M.x86.R_EIP );
|
||||
xprintf("\r\n\t");
|
||||
if (ACCESS_FLAG(F_OF)) xprintf("OV "); /* CHECKED... */
|
||||
else xprintf("NV ");
|
||||
if (ACCESS_FLAG(F_DF)) xprintf("DN ");
|
||||
else xprintf("UP ");
|
||||
if (ACCESS_FLAG(F_IF)) xprintf("EI ");
|
||||
else xprintf("DI ");
|
||||
if (ACCESS_FLAG(F_SF)) xprintf("NG ");
|
||||
else xprintf("PL ");
|
||||
if (ACCESS_FLAG(F_ZF)) xprintf("ZR ");
|
||||
else xprintf("NZ ");
|
||||
if (ACCESS_FLAG(F_AF)) xprintf("AC ");
|
||||
else xprintf("NA ");
|
||||
if (ACCESS_FLAG(F_PF)) xprintf("PE ");
|
||||
else xprintf("PO ");
|
||||
if (ACCESS_FLAG(F_CF)) xprintf("CY ");
|
||||
else xprintf("NC ");
|
||||
xprintf("\r\n");
|
||||
}
|
||||
1156
BaS_gcc/x86emu/x86decode.c
Normal file
1156
BaS_gcc/x86emu/x86decode.c
Normal file
File diff suppressed because it is too large
Load Diff
999
BaS_gcc/x86emu/x86fpu.c
Normal file
999
BaS_gcc/x86emu/x86fpu.c
Normal file
@@ -0,0 +1,999 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Realmode X86 Emulator Library
|
||||
*
|
||||
* Copyright (C) 1991-2004 SciTech Software, Inc.
|
||||
* Copyright (C) David Mosberger-Tang
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Language: ANSI C
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: This file contains the code to implement the decoding and
|
||||
* emulation of the FPU instructions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "x86debug.h"
|
||||
#include "x86emui.h"
|
||||
#include "x86fpu.h"
|
||||
#include "x86fpu_regs.h"
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
/* opcode=0xd8 */
|
||||
void x86emuOp_esc_coprocess_d8(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
START_OF_INSTR();
|
||||
DECODE_PRINTF("ESC D8\r\n");
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xd9 */
|
||||
void x86emuOp_esc_coprocess_d9(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t stkelem;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DBG_X86EMU
|
||||
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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
if (rh < 4)
|
||||
{
|
||||
DECODE_PRINTF2("ST(%d)\r\n", stkelem);
|
||||
}
|
||||
else
|
||||
{
|
||||
DECODE_PRINTF("\r\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 DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xda */
|
||||
void x86emuOp_esc_coprocess_da(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t 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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\r\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 DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xdb */
|
||||
void x86emuOp_esc_coprocess_db(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DBG_X86EMU
|
||||
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\r\n");
|
||||
break;
|
||||
case 1:
|
||||
DECODE_PRINTF("FDISI\r\n");
|
||||
break;
|
||||
case 2:
|
||||
DECODE_PRINTF("FCLEX\r\n");
|
||||
break;
|
||||
case 3:
|
||||
DECODE_PRINTF("FINIT\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DECODE_PRINTF2("ESC_DB %0x\r\n", (mod << 6) + (rh << 3) + (rl));
|
||||
}
|
||||
#endif /* DBG_X86EMU */
|
||||
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 DBG_X86EMU
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xdc */
|
||||
void x86emuOp_esc_coprocess_dc(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t 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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\r\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 DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xdd */
|
||||
void x86emuOp_esc_coprocess_dd(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t 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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\r\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 DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xde */
|
||||
void x86emuOp_esc_coprocess_de(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t 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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\r\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 DBG_X86EMU
|
||||
|
||||
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 /* DBG_X86EMU */
|
||||
|
||||
/* opcode=0xdf */
|
||||
void x86emuOp_esc_coprocess_df(uint8_t X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
unsigned int destoffset;
|
||||
uint8_t 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("\r\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\r\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (uint8_t)rl;
|
||||
DECODE_PRINTF2("\tST(%d)\r\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();
|
||||
}
|
||||
5428
BaS_gcc/x86emu/x86ops.c
Normal file
5428
BaS_gcc/x86emu/x86ops.c
Normal file
File diff suppressed because it is too large
Load Diff
1768
BaS_gcc/x86emu/x86ops2.c
Normal file
1768
BaS_gcc/x86emu/x86ops2.c
Normal file
File diff suppressed because it is too large
Load Diff
165
BaS_gcc/x86emu/x86pcibios.c
Normal file
165
BaS_gcc/x86emu/x86pcibios.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#include "radeonfb.h"
|
||||
#include "pci.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86pcibios.h"
|
||||
#include "x86debug.h"
|
||||
|
||||
extern unsigned short offset_port;
|
||||
|
||||
int x86_pcibios_emulator()
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long dev;
|
||||
|
||||
switch (X86_AX)
|
||||
{
|
||||
case PCI_BIOS_PRESENT:
|
||||
dbg("%s: PCI_BIOS_PRESENT\r\n", __FUNCTION__);
|
||||
X86_AH = 0x00; /* no config space/special cycle support */
|
||||
X86_AL = 0x01; /* config mechanism 1 */
|
||||
X86_EDX = 'P' | 'C' << 8 | 'I' << 16 | ' ' << 24;
|
||||
X86_EBX = 0x0210; /* Version 2.10 */
|
||||
X86_ECX = 0xFF00; /* FixME: Max bus number */
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case FIND_PCI_DEVICE:
|
||||
dbg("%s: FIND_PCI_DEVICE vendor = %04x, device = %04x\r\n", __FUNCTION__, X86_DX, X86_CX);
|
||||
dev = pci_find_device((unsigned long) X86_DX, ((unsigned long) X86_CX), 0);
|
||||
|
||||
if (dev != 0)
|
||||
{
|
||||
dbg("%s: ... OK\r\n", __FUNCTION__);
|
||||
X86_BH = PCI_BUS_FROM_HANDLE(dev);
|
||||
//X86_BH = (char)(dev >> 16) / PCI_MAX_FUNCTION); // dev->bus->secondary;
|
||||
X86_BL = PCI_DEVICE_FROM_HANDLE(dev) << 3 | PCI_FUNCTION_FROM_HANDLE(dev);
|
||||
//X86_BL = (char)dev; // dev->path.u.pci.devfn;
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
} else {
|
||||
dbg("%s: ... error\r\n", __FUNCTION__);
|
||||
X86_AH = DEVICE_NOT_FOUND;
|
||||
X86_EFLAGS |= FB_CF; /* set carry flag */
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case FIND_PCI_CLASS_CODE:
|
||||
/* FixME: support SI != 0 */
|
||||
dbg("%s: FIND_PCI_CLASS_CODE %x\r\n", __FUNCTION__, X86_ECX);
|
||||
dev = pci_find_classcode(X86_ECX, 0);
|
||||
if (dev != 0) {
|
||||
dbg("%s: ... OK\r\n", __FUNCTION__);
|
||||
X86_BH = PCI_BUS_FROM_HANDLE(dev);
|
||||
X86_BL = PCI_DEVICE_FROM_HANDLE(dev) << 3 | PCI_FUNCTION_FROM_HANDLE(dev);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg("%s: ... error\r\n", __FUNCTION__);
|
||||
X86_AH = DEVICE_NOT_FOUND;
|
||||
X86_EFLAGS |= FB_CF; /* set carry flag */
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case READ_CONFIG_BYTE:
|
||||
// bus, devfn
|
||||
dbg("%s: READ_CONFIG_BYTE bus = %x, devfn = %x, reg = %x\r\n", __FUNCTION__, X86_BH, X86_BL, X86_DI);
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
X86_CL = pci_read_config_byte(dev, X86_DI);
|
||||
dbg("%s: value = %x\r\n", __FUNCTION__, X86_CL);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case READ_CONFIG_WORD:
|
||||
// bus, devfn
|
||||
dbg("%s: READ_CONFIG_WORD bus = %x, devfn = %x, reg = %x\r\n", __FUNCTION__, X86_BH, X86_BL, X86_DI);
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
if(X86_DI == PCIBAR1)
|
||||
X86_CX = offset_port + 1;
|
||||
else
|
||||
X86_CX = pci_read_config_word(dev, X86_DI);
|
||||
dbg("%s: value = %x\r\n", __FUNCTION__, X86_CX);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case READ_CONFIG_DWORD:
|
||||
// bus, devfn
|
||||
dbg("%s: READ_CONFIG_DWORD bus = %x, devfn = %x, reg = %x\r\n", __FUNCTION__, X86_BH, X86_BL, X86_DI);
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
if (X86_DI == PCIBAR1)
|
||||
X86_CX = (unsigned long) offset_port + 1;
|
||||
else
|
||||
X86_ECX = pci_read_config_longword(dev, X86_DI);
|
||||
dbg("%s: value = %x\r\n", __FUNCTION__, X86_ECX);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case WRITE_CONFIG_BYTE:
|
||||
// bus, devfn
|
||||
dbg("%s: READ_CONFIG_BYTE bus = %x, devfn = %x, reg = %x, value = %x\r\n", __FUNCTION__,
|
||||
X86_BH, X86_BL, X86_DI, X86_CL);
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
pci_write_config_byte(dev, X86_DI, X86_CL);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case WRITE_CONFIG_WORD:
|
||||
// bus, devfn
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
dbg("%s: WRITE_CONFIG_WORD bus = %x, devfn = %x, reg = %x, value = %x\r\n", X86_BH, X86_BL, X86_DI, X86_CX);
|
||||
if (X86_DI == PCIBAR1)
|
||||
{
|
||||
offset_port = X86_CX;
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
pci_write_config_word(dev, X86_DI, X86_CX);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case WRITE_CONFIG_DWORD:
|
||||
// bus, devfn
|
||||
dev = PCI_HANDLE(X86_BH, X86_BL >> 3, X86_BL & 3);
|
||||
dbg("%s: WRITE_CONFIG_DWORD bus = %x, devfn = %x, value = %x\r\n", __FUNCTION__,
|
||||
X86_BH, X86_BL, X86_DI, X86_ECX);
|
||||
if (X86_DI == PCIBAR1)
|
||||
{
|
||||
offset_port = (unsigned short) X86_ECX & 0xFFFC;
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
pci_write_config_longword(dev, X86_DI, X86_ECX);
|
||||
X86_AH = SUCCESSFUL;
|
||||
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
dbg("%s: PCI_BIOS FUNC_NOT_SUPPORTED\r\n", __FUNCTION__);
|
||||
X86_AH = FUNC_NOT_SUPPORTED;
|
||||
X86_EFLAGS |= FB_CF;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
2452
BaS_gcc/x86emu/x86prim_ops.c
Normal file
2452
BaS_gcc/x86emu/x86prim_ops.c
Normal file
File diff suppressed because it is too large
Load Diff
470
BaS_gcc/x86emu/x86sys.c
Normal file
470
BaS_gcc/x86emu/x86sys.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 "radeonfb.h"
|
||||
#include "pci.h"
|
||||
|
||||
#include "x86emu.h"
|
||||
#include "x86regs.h"
|
||||
#include "x86debug.h"
|
||||
#include "x86prim_ops.h"
|
||||
|
||||
extern uint8_t inb(uint16_t port);
|
||||
extern uint16_t inw(uint16_t port);
|
||||
extern uint32_t inl(uint16_t port);
|
||||
extern void outb(uint8_t val, uint16_t port);
|
||||
extern void outw(uint16_t val, uint16_t port);
|
||||
extern void outl(uint32_t val, uint16_t port);
|
||||
|
||||
/*------------------------- Global Variables ------------------------------*/
|
||||
|
||||
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
|
||||
X86EMU_intrFuncs _X86EMU_intrTab[256];
|
||||
extern struct radeonfb_info *rinfo_biosemu;
|
||||
extern uint32_t offset_mem;
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - Emulator memory address to read
|
||||
*
|
||||
* RETURNS:
|
||||
* Byte value read from emulator memory.
|
||||
*
|
||||
* REMARKS:
|
||||
* Reads a byte value from the emulator memory.
|
||||
*/
|
||||
inline uint8_t X86API rdb(uint32_t addr)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
val = *(uint8_t *) (offset_mem + addr);
|
||||
dbg("%s: rdb(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
dbg("%s: %p 1 -> %x\r\n", __FUNCTION__, 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.
|
||||
*/
|
||||
uint16_t X86API rdw(uint32_t addr)
|
||||
{
|
||||
uint16_t val;
|
||||
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
val = swpw(*(uint16_t *)(offset_mem+addr));
|
||||
dbg("%s: rdw(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (uint16_t) (* (uint8_t *)(M.mem_base + addr));
|
||||
val |= (((uint16_t)( *(uint8_t *)(M.mem_base + addr + 1))) << 8);
|
||||
}
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
dbg("%s: %p 2 -> %x\r\n", __FUNCTION__, 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.
|
||||
*/
|
||||
inline uint32_t X86API rdl(uint32_t addr)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
val = swpl(*(uint32_t *)(offset_mem + addr));
|
||||
dbg("%s: rdl(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = swpl(*(uint32_t *)(M.mem_base + addr));
|
||||
}
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
|
||||
dbg("%s: %p 4 -> %x\r\n", __FUNCTION__, addr, val);
|
||||
} )
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - Emulator memory address to read
|
||||
* val - Value to store
|
||||
*
|
||||
* REMARKS:
|
||||
* Writes a byte value to emulator memory.
|
||||
*/
|
||||
inline void X86API wrb(uint32_t addr, uint8_t val)
|
||||
{
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
*(uint8_t *)(offset_mem + addr) = val;
|
||||
dbg("%s: wrb(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr >= M.mem_size)
|
||||
{
|
||||
DB(
|
||||
{
|
||||
dbg("%s: mem_ptr: %p out of range!\r\n", __FUNCTION__, addr);
|
||||
})
|
||||
HALT_SYS();
|
||||
}
|
||||
*(uint8_t *)(M.mem_base + addr) = val;
|
||||
}
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
dbg("%s: %p 1 < %x\r\n", __FUNCTION__, addr, val);
|
||||
} )
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - Emulator memory address to read
|
||||
* val - Value to store
|
||||
*
|
||||
* REMARKS:
|
||||
* Writes a word value to emulator memory.
|
||||
*/
|
||||
inline void X86API wrw(uint32_t addr, uint16_t val)
|
||||
{
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
dbg("%s: wrw(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
*(uint16_t *)(offset_mem+addr) = swpw(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr > M.mem_size - 2)
|
||||
{
|
||||
DB(
|
||||
{
|
||||
dbg("%s: mem_ptr: %p out of range\r\n", __FUNCTION__, addr);
|
||||
})
|
||||
HALT_SYS();
|
||||
}
|
||||
*(uint8_t *)(M.mem_base + addr) = (uint8_t) val;
|
||||
*(uint8_t *)(M.mem_base + addr + 1) = (uint8_t) (val >> 8);
|
||||
}
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
dbg("%s: %p 2 <- %x\r\n", __FUNCTION__, addr, val);
|
||||
} )
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - Emulator memory address to read
|
||||
* val - Value to store
|
||||
*
|
||||
* REMARKS:
|
||||
* Writes a long value to emulator memory.
|
||||
*/
|
||||
inline void X86API wrl(uint32_t addr, uint32_t val)
|
||||
{
|
||||
if ((addr >= 0xA0000) && (addr <= 0xBFFFF))
|
||||
{
|
||||
dbg("%s: wrl(%x) = %x\r\n", __FUNCTION__, addr, val);
|
||||
*(uint32_t *)(offset_mem+addr) = swpl(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addr > M.mem_size - 4)
|
||||
{
|
||||
DB(
|
||||
{
|
||||
dbg("%s: mem_ptr: address %x out of range!\r\n", __FUNCTION__, addr);
|
||||
}
|
||||
)
|
||||
HALT_SYS();
|
||||
}
|
||||
*(uint32_t *)(M.mem_base + addr) = swpl(val);
|
||||
}
|
||||
DB(if (DEBUG_MEM_TRACE())
|
||||
{
|
||||
dbg("%s: %p 4 <- %x\r\n", __FUNCTION__, addr, val);
|
||||
} )
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - PIO address to read
|
||||
* RETURN:
|
||||
* 0
|
||||
* REMARKS:
|
||||
* Default PIO byte read function. Doesn't perform real inb.
|
||||
*/
|
||||
inline uint8_t X86API p_inb(X86EMU_pioAddr addr)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("%s: inb(%p)\r\n", __FUNCTION__);
|
||||
} )
|
||||
return inb(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - PIO address to read
|
||||
* RETURN:
|
||||
* 0
|
||||
* REMARKS:
|
||||
* Default PIO word read function. Doesn't perform real inw.
|
||||
*/
|
||||
inline uint16_t X86API p_inw(X86EMU_pioAddr addr)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("%s: inw(%p)\r\n", __FUNCTION__, addr);
|
||||
} )
|
||||
return inw(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* PARAMETERS:
|
||||
* addr - PIO address to read
|
||||
* RETURN:
|
||||
* 0
|
||||
* REMARKS:
|
||||
* Default PIO long read function. Doesn't perform real inl.
|
||||
*/
|
||||
inline uint32_t X86API p_inl(X86EMU_pioAddr addr)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("%s: inl %p\r\n", __FUNCTION__, 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.
|
||||
*/
|
||||
inline void X86API p_outb(X86EMU_pioAddr addr, uint8_t val)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("%s: outb %x -> %x\r\n", __FUNCTION__, val, 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.
|
||||
*/
|
||||
inline void X86API p_outw(X86EMU_pioAddr addr, uint16_t val)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("outw %x -> %x\r\n", __FUNCTION__, val, 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.
|
||||
*/
|
||||
inline void X86API p_outl(X86EMU_pioAddr addr, uint32_t val)
|
||||
{
|
||||
DB(if (DEBUG_IO_TRACE())
|
||||
{
|
||||
dbg("%s: outl %x -> %x\r\n", __FUNCTION__, val, addr);
|
||||
} )
|
||||
outl(val, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------- Global Variables ------------------------------*/
|
||||
|
||||
uint8_t(X86APIP sys_rdb) (uint32_t addr) = rdb;
|
||||
uint16_t(X86APIP sys_rdw) (uint32_t addr) = rdw;
|
||||
uint32_t(X86APIP sys_rdl) (uint32_t addr) = rdl;
|
||||
void (X86APIP sys_wrb) (uint32_t addr, uint8_t val) = wrb;
|
||||
void (X86APIP sys_wrw) (uint32_t addr, uint16_t val) = wrw;
|
||||
void (X86APIP sys_wrl) (uint32_t addr, uint32_t val) = wrl;
|
||||
uint8_t(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
|
||||
uint16_t(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
|
||||
uint32_t(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
|
||||
void (X86APIP sys_outb) (X86EMU_pioAddr addr, uint8_t val) = p_outb;
|
||||
void (X86APIP sys_outw) (X86EMU_pioAddr addr, uint16_t val) = p_outw;
|
||||
void (X86APIP sys_outl) (X86EMU_pioAddr addr, uint32_t val) = p_outl;
|
||||
|
||||
/*----------------------------- Setup -------------------------------------*/
|
||||
|
||||
#if 0 // cannot works whith data in flash
|
||||
/****************************************************************************
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
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((uint16_t) 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, unsigned long size)
|
||||
{
|
||||
M.mem_base = (int) base;
|
||||
M.mem_size = size;
|
||||
}
|
||||
Reference in New Issue
Block a user