released 0.8.7 (new MMU layout, m5484LITE board working again)

This commit is contained in:
Markus Fröschle
2015-01-24 10:24:33 +00:00
parent f72b551170
commit ce6e8d58fd
284 changed files with 126529 additions and 0 deletions

403
BaS_gcc/x86emu/x86biosemu.c Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

999
BaS_gcc/x86emu/x86fpu.c Normal file
View 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

File diff suppressed because it is too large Load Diff

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
View 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

File diff suppressed because it is too large Load Diff

470
BaS_gcc/x86emu/x86sys.c Normal file
View 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;
}