mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
i386.cpp: prepare to change hxx files into regular cpp files (nw)
-change order of include files at top of i386.cpp -move some routines between i386.cpp and i386priv.h -move part of x87ops.hxx into new file x87priv.h . Now you only have to rename the hxx files to cpp and add the following at the top of each one . #include "emu.h" #include "i386.h" #include "i386priv.h" #include "x87priv.h" #include "cycles.h" #include "debugger.h" #include "debug/debugcpu.h" #undef i386
This commit is contained in:
parent
cbd7b12f60
commit
4f5f5c6c92
@ -1072,6 +1072,7 @@ if (CPUS["I386"]~=null) then
|
||||
MAME_DIR .. "src/devices/cpu/i386/i486ops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/pentops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/x87ops.hxx",
|
||||
MAME_DIR .. "src/devices/cpu/i386/x87priv.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -20,10 +20,12 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "i386.h"
|
||||
#include "i386priv.h"
|
||||
#include "x87priv.h"
|
||||
#include "cycles.h"
|
||||
#include "i386ops.h"
|
||||
|
||||
#include "debugger.h"
|
||||
#include "i386priv.h"
|
||||
|
||||
#include "debug/debugcpu.h"
|
||||
|
||||
/* seems to be defined on mingw-gcc */
|
||||
@ -154,11 +156,167 @@ device_memory_interface::space_config_vector i386_device::memory_space_config()
|
||||
int i386_parity_table[256];
|
||||
MODRM_TABLE i386_MODRM_table[256];
|
||||
|
||||
#define FAULT(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,0,error); return;}
|
||||
#define FAULT_EXP(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn)
|
||||
{
|
||||
// TODO: segment limit access size, execution permission, handle exception thrown from exception handler
|
||||
if (PROTECTED_MODE && !V8086_MODE && (rwn != -1))
|
||||
{
|
||||
if (!(m_sreg[segment].valid))
|
||||
FAULT_THROW((segment == SS) ? FAULT_SS : FAULT_GP, 0);
|
||||
if (i386_limit_check(segment, ip))
|
||||
FAULT_THROW((segment == SS) ? FAULT_SS : FAULT_GP, 0);
|
||||
if ((rwn == 0) && ((m_sreg[segment].flags & 8) && !(m_sreg[segment].flags & 2)))
|
||||
FAULT_THROW(FAULT_GP, 0);
|
||||
if ((rwn == 1) && ((m_sreg[segment].flags & 8) || !(m_sreg[segment].flags & 2)))
|
||||
FAULT_THROW(FAULT_GP, 0);
|
||||
}
|
||||
return m_sreg[segment].base + ip;
|
||||
}
|
||||
|
||||
vtlb_entry i386_device::get_permissions(uint32_t pte, int wp)
|
||||
{
|
||||
vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
|
||||
if (!wp)
|
||||
ret |= VTLB_WRITE_ALLOWED;
|
||||
if (pte & 2)
|
||||
ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_entry *entry)
|
||||
{
|
||||
uint32_t a = *address;
|
||||
uint32_t pdbr = m_cr[3] & 0xfffff000;
|
||||
uint32_t directory = (a >> 22) & 0x3ff;
|
||||
uint32_t table = (a >> 12) & 0x3ff;
|
||||
vtlb_entry perm = 0;
|
||||
bool ret;
|
||||
bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
|
||||
bool write = (intention & TRANSLATE_WRITE) ? true : false;
|
||||
bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
|
||||
|
||||
if (!(m_cr[0] & 0x80000000))
|
||||
{
|
||||
if (entry)
|
||||
*entry = 0x77;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t page_dir = m_program->read_dword(pdbr + directory * 4);
|
||||
if (page_dir & 1)
|
||||
{
|
||||
if ((page_dir & 0x80) && (m_cr[4] & 0x10))
|
||||
{
|
||||
a = (page_dir & 0xffc00000) | (a & 0x003fffff);
|
||||
if (debug)
|
||||
{
|
||||
*address = a;
|
||||
return true;
|
||||
}
|
||||
perm = get_permissions(page_dir, WP);
|
||||
if (write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
|
||||
ret = false;
|
||||
else if (user && !(perm & VTLB_USER_READ_ALLOWED))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
if (write)
|
||||
perm |= VTLB_FLAG_DIRTY;
|
||||
if (!(page_dir & 0x40) && write)
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x60);
|
||||
else if (!(page_dir & 0x20))
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t page_entry = m_program->read_dword((page_dir & 0xfffff000) + (table * 4));
|
||||
if (!(page_entry & 1))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
a = (page_entry & 0xfffff000) | (a & 0xfff);
|
||||
if (debug)
|
||||
{
|
||||
*address = a;
|
||||
return true;
|
||||
}
|
||||
perm = get_permissions(page_entry, WP);
|
||||
if (write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
|
||||
ret = false;
|
||||
else if (user && !(perm & VTLB_USER_READ_ALLOWED))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
if (write)
|
||||
perm |= VTLB_FLAG_DIRTY;
|
||||
if (!(page_dir & 0x20))
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
|
||||
if (!(page_entry & 0x40) && write)
|
||||
m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
|
||||
else if (!(page_entry & 0x20))
|
||||
m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
if (entry)
|
||||
*entry = perm;
|
||||
if (ret)
|
||||
*address = a;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//#define TEST_TLB
|
||||
|
||||
bool i386_device::translate_address(int pl, int type, uint32_t *address, uint32_t *error)
|
||||
{
|
||||
if (!(m_cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this
|
||||
return true;
|
||||
|
||||
const vtlb_entry *table = vtlb_table();
|
||||
uint32_t index = *address >> 12;
|
||||
vtlb_entry entry = table[index];
|
||||
if (type == TRANSLATE_FETCH)
|
||||
type = TRANSLATE_READ;
|
||||
if (pl == 3)
|
||||
type |= TRANSLATE_USER_MASK;
|
||||
#ifdef TEST_TLB
|
||||
uint32_t test_addr = *address;
|
||||
#endif
|
||||
|
||||
if (!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
|
||||
{
|
||||
if (!i386_translate_address(type, address, &entry))
|
||||
{
|
||||
*error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0);
|
||||
if (entry)
|
||||
*error |= 1;
|
||||
return false;
|
||||
}
|
||||
vtlb_dynload(index, *address, entry);
|
||||
return true;
|
||||
}
|
||||
if (!(entry & (1 << type)))
|
||||
{
|
||||
*error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0) | 1;
|
||||
return false;
|
||||
}
|
||||
*address = (entry & 0xfffff000) | (*address & 0xfff);
|
||||
#ifdef TEST_TLB
|
||||
int test_ret = i386_translate_address(type | TRANSLATE_DEBUG_MASK, &test_addr, nullptr);
|
||||
if (!test_ret || (test_addr != *address))
|
||||
logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, m_pc);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t i386_device::i386_load_protected_mode_segment(I386_SREG *seg, uint64_t *desc )
|
||||
{
|
||||
uint32_t v1,v2;
|
||||
@ -2824,48 +2982,6 @@ void i386_device::i386_protected_mode_iret(int operand32)
|
||||
CHANGE_PC(m_eip);
|
||||
}
|
||||
|
||||
#include "cycles.h"
|
||||
|
||||
#define CYCLES_NUM(x) (m_cycles -= (x))
|
||||
|
||||
void i386_device::CYCLES(int x)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[x];
|
||||
}
|
||||
}
|
||||
|
||||
void i386_device::CYCLES_RM(int modrm, int r, int m)
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[r];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[r];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[m];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i386_device::build_cycle_table()
|
||||
{
|
||||
int i, j;
|
||||
@ -2915,7 +3031,6 @@ void i386_device::report_invalid_modrm(const char* opcode, uint8_t modrm)
|
||||
#include "i486ops.hxx"
|
||||
#include "pentops.hxx"
|
||||
#include "x87ops.hxx"
|
||||
#include "i386ops.h"
|
||||
|
||||
void i386_device::i386_decode_opcode()
|
||||
{
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef __I386_H__
|
||||
#define __I386_H__
|
||||
|
||||
#include "i386.h"
|
||||
#include "i386dasm.h"
|
||||
|
||||
//#define DEBUG_MISSING_OPCODE
|
||||
@ -322,6 +321,12 @@ extern int i386_parity_table[256];
|
||||
#define MMX(n) (*((MMX_REG *)(&m_x87_reg[(n)].low)))
|
||||
#define XMM(n) m_sse_reg[(n)]
|
||||
|
||||
#define VTLB_FLAG_DIRTY 0x100
|
||||
#define CYCLES_NUM(x) (m_cycles -= (x))
|
||||
|
||||
#define FAULT(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,0,error); return;}
|
||||
#define FAULT_EXP(fault,error) {m_ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
|
||||
|
||||
/***********************************************************************************/
|
||||
|
||||
struct MODRM_TABLE {
|
||||
@ -361,167 +366,6 @@ extern MODRM_TABLE i386_MODRM_table[256];
|
||||
|
||||
/***********************************************************************************/
|
||||
|
||||
uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn)
|
||||
{
|
||||
// TODO: segment limit access size, execution permission, handle exception thrown from exception handler
|
||||
if(PROTECTED_MODE && !V8086_MODE && (rwn != -1))
|
||||
{
|
||||
if(!(m_sreg[segment].valid))
|
||||
FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
|
||||
if(i386_limit_check(segment, ip))
|
||||
FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
|
||||
if((rwn == 0) && ((m_sreg[segment].flags & 8) && !(m_sreg[segment].flags & 2)))
|
||||
FAULT_THROW(FAULT_GP, 0);
|
||||
if((rwn == 1) && ((m_sreg[segment].flags & 8) || !(m_sreg[segment].flags & 2)))
|
||||
FAULT_THROW(FAULT_GP, 0);
|
||||
}
|
||||
return m_sreg[segment].base + ip;
|
||||
}
|
||||
|
||||
#define VTLB_FLAG_DIRTY 0x100
|
||||
|
||||
vtlb_entry i386_device::get_permissions(uint32_t pte, int wp)
|
||||
{
|
||||
vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
|
||||
if(!wp)
|
||||
ret |= VTLB_WRITE_ALLOWED;
|
||||
if(pte & 2)
|
||||
ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_entry *entry)
|
||||
{
|
||||
uint32_t a = *address;
|
||||
uint32_t pdbr = m_cr[3] & 0xfffff000;
|
||||
uint32_t directory = (a >> 22) & 0x3ff;
|
||||
uint32_t table = (a >> 12) & 0x3ff;
|
||||
vtlb_entry perm = 0;
|
||||
bool ret;
|
||||
bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
|
||||
bool write = (intention & TRANSLATE_WRITE) ? true : false;
|
||||
bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
|
||||
|
||||
if(!(m_cr[0] & 0x80000000))
|
||||
{
|
||||
if(entry)
|
||||
*entry = 0x77;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t page_dir = m_program->read_dword(pdbr + directory * 4);
|
||||
if(page_dir & 1)
|
||||
{
|
||||
if ((page_dir & 0x80) && (m_cr[4] & 0x10))
|
||||
{
|
||||
a = (page_dir & 0xffc00000) | (a & 0x003fffff);
|
||||
if(debug)
|
||||
{
|
||||
*address = a;
|
||||
return true;
|
||||
}
|
||||
perm = get_permissions(page_dir, WP);
|
||||
if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
|
||||
ret = false;
|
||||
else if(user && !(perm & VTLB_USER_READ_ALLOWED))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
if(write)
|
||||
perm |= VTLB_FLAG_DIRTY;
|
||||
if(!(page_dir & 0x40) && write)
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x60);
|
||||
else if(!(page_dir & 0x20))
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t page_entry = m_program->read_dword((page_dir & 0xfffff000) + (table * 4));
|
||||
if(!(page_entry & 1))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
a = (page_entry & 0xfffff000) | (a & 0xfff);
|
||||
if(debug)
|
||||
{
|
||||
*address = a;
|
||||
return true;
|
||||
}
|
||||
perm = get_permissions(page_entry, WP);
|
||||
if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
|
||||
ret = false;
|
||||
else if(user && !(perm & VTLB_USER_READ_ALLOWED))
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
if(write)
|
||||
perm |= VTLB_FLAG_DIRTY;
|
||||
if(!(page_dir & 0x20))
|
||||
m_program->write_dword(pdbr + directory * 4, page_dir | 0x20);
|
||||
if(!(page_entry & 0x40) && write)
|
||||
m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
|
||||
else if(!(page_entry & 0x20))
|
||||
m_program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
if(entry)
|
||||
*entry = perm;
|
||||
if(ret)
|
||||
*address = a;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//#define TEST_TLB
|
||||
|
||||
bool i386_device::translate_address(int pl, int type, uint32_t *address, uint32_t *error)
|
||||
{
|
||||
if(!(m_cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this
|
||||
return true;
|
||||
|
||||
const vtlb_entry *table = vtlb_table();
|
||||
uint32_t index = *address >> 12;
|
||||
vtlb_entry entry = table[index];
|
||||
if(type == TRANSLATE_FETCH)
|
||||
type = TRANSLATE_READ;
|
||||
if(pl == 3)
|
||||
type |= TRANSLATE_USER_MASK;
|
||||
#ifdef TEST_TLB
|
||||
uint32_t test_addr = *address;
|
||||
#endif
|
||||
|
||||
if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
|
||||
{
|
||||
if(!i386_translate_address(type, address, &entry))
|
||||
{
|
||||
*error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0);
|
||||
if(entry)
|
||||
*error |= 1;
|
||||
return false;
|
||||
}
|
||||
vtlb_dynload(index, *address, entry);
|
||||
return true;
|
||||
}
|
||||
if(!(entry & (1 << type)))
|
||||
{
|
||||
*error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0) | 1;
|
||||
return false;
|
||||
}
|
||||
*address = (entry & 0xfffff000) | (*address & 0xfff);
|
||||
#ifdef TEST_TLB
|
||||
int test_ret = i386_translate_address(type | TRANSLATE_DEBUG_MASK, &test_addr, nullptr);
|
||||
if(!test_ret || (test_addr != *address))
|
||||
logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, m_pc);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void i386_device::CHANGE_PC(uint32_t pc)
|
||||
{
|
||||
m_pc = i386_translate(CS, pc, -1 );
|
||||
@ -1093,6 +937,44 @@ void i386_device::BUMP_DI(int adjustment)
|
||||
REG16(DI) += ((m_DF) ? -adjustment : +adjustment);
|
||||
}
|
||||
|
||||
void i386_device::CYCLES(int x)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[x];
|
||||
}
|
||||
}
|
||||
|
||||
void i386_device::CYCLES_RM(int modrm, int r, int m)
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[r];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[r];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
m_cycles -= m_cycle_table_pm[m];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cycles -= m_cycle_table_rm[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
|
@ -24,168 +24,6 @@
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Defines
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#define X87_SW_IE 0x0001
|
||||
#define X87_SW_DE 0x0002
|
||||
#define X87_SW_ZE 0x0004
|
||||
#define X87_SW_OE 0x0008
|
||||
#define X87_SW_UE 0x0010
|
||||
#define X87_SW_PE 0x0020
|
||||
#define X87_SW_SF 0x0040
|
||||
#define X87_SW_ES 0x0080
|
||||
#define X87_SW_C0 0x0100
|
||||
#define X87_SW_C1 0x0200
|
||||
#define X87_SW_C2 0x0400
|
||||
#define X87_SW_TOP_SHIFT 11
|
||||
#define X87_SW_TOP_MASK 7
|
||||
#define X87_SW_C3 0x4000
|
||||
#define X87_SW_BUSY 0x8000
|
||||
|
||||
#define X87_CW_IM 0x0001
|
||||
#define X87_CW_DM 0x0002
|
||||
#define X87_CW_ZM 0x0004
|
||||
#define X87_CW_OM 0x0008
|
||||
#define X87_CW_UM 0x0010
|
||||
#define X87_CW_PM 0x0020
|
||||
#define X87_CW_IEM 0x0080
|
||||
#define X87_CW_PC_SHIFT 8
|
||||
#define X87_CW_PC_MASK 3
|
||||
#define X87_CW_PC_SINGLE 0
|
||||
#define X87_CW_PC_DOUBLE 2
|
||||
#define X87_CW_PC_EXTEND 3
|
||||
#define X87_CW_RC_SHIFT 10
|
||||
#define X87_CW_RC_MASK 3
|
||||
#define X87_CW_RC_NEAREST 0
|
||||
#define X87_CW_RC_DOWN 1
|
||||
#define X87_CW_RC_UP 2
|
||||
#define X87_CW_RC_ZERO 3
|
||||
|
||||
#define X87_TW_MASK 3
|
||||
#define X87_TW_VALID 0
|
||||
#define X87_TW_ZERO 1
|
||||
#define X87_TW_SPECIAL 2
|
||||
#define X87_TW_EMPTY 3
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Macros
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#define ST_TO_PHYS(x) (((m_x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK)
|
||||
#define ST(x) (m_x87_reg[ST_TO_PHYS(x)])
|
||||
#define X87_TW_FIELD_SHIFT(x) ((x) << 1)
|
||||
#define X87_TAG(x) ((m_x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK)
|
||||
#define X87_RC ((m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK)
|
||||
#define X87_IS_ST_EMPTY(x) (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY)
|
||||
#define X87_SW_C3_0 X87_SW_C0
|
||||
|
||||
#define UNIMPLEMENTED fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, m_pc)
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Constants
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const floatx80 fx80_zero = { 0x0000, 0x0000000000000000U };
|
||||
static const floatx80 fx80_one = { 0x3fff, 0x8000000000000000U };
|
||||
|
||||
static const floatx80 fx80_ninf = { 0xffff, 0x8000000000000000U };
|
||||
static const floatx80 fx80_inan = { 0xffff, 0xc000000000000000U };
|
||||
|
||||
/* Maps x87 round modes to SoftFloat round modes */
|
||||
static const int x87_to_sf_rc[4] =
|
||||
{
|
||||
float_round_nearest_even,
|
||||
float_round_down,
|
||||
float_round_up,
|
||||
float_round_to_zero,
|
||||
};
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* SoftFloat helpers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
extern flag floatx80_is_nan( floatx80 a );
|
||||
|
||||
extern flag floatx80_is_signaling_nan(floatx80 a);
|
||||
|
||||
static inline flag floatx80_is_quiet_nan(floatx80 a)
|
||||
{
|
||||
bits64 aLow;
|
||||
|
||||
aLow = a.low & ~LIT64(0x4000000000000000);
|
||||
return
|
||||
((a.high & 0x7FFF) == 0x7FFF)
|
||||
&& (bits64)(aLow << 1)
|
||||
&& (a.low != aLow);
|
||||
}
|
||||
|
||||
static inline int floatx80_is_zero(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0));
|
||||
}
|
||||
|
||||
static inline int floatx80_is_inf(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0));
|
||||
}
|
||||
|
||||
static inline int floatx80_is_denormal(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0) &&
|
||||
((fx.low & 0x8000000000000000U) == 0) &&
|
||||
((fx.low << 1) != 0));
|
||||
}
|
||||
|
||||
static inline floatx80 floatx80_abs(floatx80 fx)
|
||||
{
|
||||
fx.high &= 0x7fff;
|
||||
return fx;
|
||||
}
|
||||
|
||||
static inline double fx80_to_double(floatx80 fx)
|
||||
{
|
||||
uint64_t d = floatx80_to_float64(fx);
|
||||
return *(double*)&d;
|
||||
}
|
||||
|
||||
static inline floatx80 double_to_fx80(double in)
|
||||
{
|
||||
return float64_to_floatx80(*(uint64_t*)&in);
|
||||
}
|
||||
|
||||
floatx80 i386_device::READ80(uint32_t ea)
|
||||
{
|
||||
floatx80 t;
|
||||
|
||||
t.low = READ64(ea);
|
||||
t.high = READ16(ea + 8);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void i386_device::WRITE80(uint32_t ea, floatx80 t)
|
||||
{
|
||||
WRITE64(ea, t.low);
|
||||
WRITE16(ea + 8, t.high);
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* x87 stack handling
|
||||
@ -353,7 +191,6 @@ void i386_device::x87_reset()
|
||||
m_ferr_handler(0);
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Core arithmetic
|
||||
|
169
src/devices/cpu/i386/x87priv.h
Normal file
169
src/devices/cpu/i386/x87priv.h
Normal file
@ -0,0 +1,169 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Philip Bennett
|
||||
#pragma once
|
||||
|
||||
#ifndef __X87PRIV_H__
|
||||
#define __X87PRIV_H__
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Defines
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#define X87_SW_IE 0x0001
|
||||
#define X87_SW_DE 0x0002
|
||||
#define X87_SW_ZE 0x0004
|
||||
#define X87_SW_OE 0x0008
|
||||
#define X87_SW_UE 0x0010
|
||||
#define X87_SW_PE 0x0020
|
||||
#define X87_SW_SF 0x0040
|
||||
#define X87_SW_ES 0x0080
|
||||
#define X87_SW_C0 0x0100
|
||||
#define X87_SW_C1 0x0200
|
||||
#define X87_SW_C2 0x0400
|
||||
#define X87_SW_TOP_SHIFT 11
|
||||
#define X87_SW_TOP_MASK 7
|
||||
#define X87_SW_C3 0x4000
|
||||
#define X87_SW_BUSY 0x8000
|
||||
|
||||
#define X87_CW_IM 0x0001
|
||||
#define X87_CW_DM 0x0002
|
||||
#define X87_CW_ZM 0x0004
|
||||
#define X87_CW_OM 0x0008
|
||||
#define X87_CW_UM 0x0010
|
||||
#define X87_CW_PM 0x0020
|
||||
#define X87_CW_IEM 0x0080
|
||||
#define X87_CW_PC_SHIFT 8
|
||||
#define X87_CW_PC_MASK 3
|
||||
#define X87_CW_PC_SINGLE 0
|
||||
#define X87_CW_PC_DOUBLE 2
|
||||
#define X87_CW_PC_EXTEND 3
|
||||
#define X87_CW_RC_SHIFT 10
|
||||
#define X87_CW_RC_MASK 3
|
||||
#define X87_CW_RC_NEAREST 0
|
||||
#define X87_CW_RC_DOWN 1
|
||||
#define X87_CW_RC_UP 2
|
||||
#define X87_CW_RC_ZERO 3
|
||||
|
||||
#define X87_TW_MASK 3
|
||||
#define X87_TW_VALID 0
|
||||
#define X87_TW_ZERO 1
|
||||
#define X87_TW_SPECIAL 2
|
||||
#define X87_TW_EMPTY 3
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Macros
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#define ST_TO_PHYS(x) (((m_x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK)
|
||||
#define ST(x) (m_x87_reg[ST_TO_PHYS(x)])
|
||||
#define X87_TW_FIELD_SHIFT(x) ((x) << 1)
|
||||
#define X87_TAG(x) ((m_x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK)
|
||||
#define X87_RC ((m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK)
|
||||
#define X87_IS_ST_EMPTY(x) (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY)
|
||||
#define X87_SW_C3_0 X87_SW_C0
|
||||
|
||||
#define UNIMPLEMENTED fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, m_pc)
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Constants
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const floatx80 fx80_zero = { 0x0000, 0x0000000000000000U };
|
||||
static const floatx80 fx80_one = { 0x3fff, 0x8000000000000000U };
|
||||
|
||||
static const floatx80 fx80_ninf = { 0xffff, 0x8000000000000000U };
|
||||
static const floatx80 fx80_inan = { 0xffff, 0xc000000000000000U };
|
||||
|
||||
/* Maps x87 round modes to SoftFloat round modes */
|
||||
static const int x87_to_sf_rc[4] =
|
||||
{
|
||||
float_round_nearest_even,
|
||||
float_round_down,
|
||||
float_round_up,
|
||||
float_round_to_zero,
|
||||
};
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* SoftFloat helpers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
extern flag floatx80_is_nan(floatx80 a);
|
||||
|
||||
extern flag floatx80_is_signaling_nan(floatx80 a);
|
||||
|
||||
static inline flag floatx80_is_quiet_nan(floatx80 a)
|
||||
{
|
||||
bits64 aLow;
|
||||
|
||||
aLow = a.low & ~LIT64(0x4000000000000000);
|
||||
return
|
||||
((a.high & 0x7FFF) == 0x7FFF)
|
||||
&& (bits64)(aLow << 1)
|
||||
&& (a.low != aLow);
|
||||
}
|
||||
|
||||
static inline int floatx80_is_zero(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0));
|
||||
}
|
||||
|
||||
static inline int floatx80_is_inf(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0));
|
||||
}
|
||||
|
||||
static inline int floatx80_is_denormal(floatx80 fx)
|
||||
{
|
||||
return (((fx.high & 0x7fff) == 0) &&
|
||||
((fx.low & 0x8000000000000000U) == 0) &&
|
||||
((fx.low << 1) != 0));
|
||||
}
|
||||
|
||||
static inline floatx80 floatx80_abs(floatx80 fx)
|
||||
{
|
||||
fx.high &= 0x7fff;
|
||||
return fx;
|
||||
}
|
||||
|
||||
static inline double fx80_to_double(floatx80 fx)
|
||||
{
|
||||
uint64_t d = floatx80_to_float64(fx);
|
||||
return *(double*)&d;
|
||||
}
|
||||
|
||||
static inline floatx80 double_to_fx80(double in)
|
||||
{
|
||||
return float64_to_floatx80(*(uint64_t*)&in);
|
||||
}
|
||||
|
||||
floatx80 i386_device::READ80(uint32_t ea)
|
||||
{
|
||||
floatx80 t;
|
||||
|
||||
t.low = READ64(ea);
|
||||
t.high = READ16(ea + 8);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void i386_device::WRITE80(uint32_t ea, floatx80 t)
|
||||
{
|
||||
WRITE64(ea, t.low);
|
||||
WRITE16(ea + 8, t.high);
|
||||
}
|
||||
|
||||
#endif /* __X87PRIV_H__ */
|
Loading…
Reference in New Issue
Block a user