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:
yz70s 2018-11-03 10:21:04 +01:00
parent cbd7b12f60
commit 4f5f5c6c92
5 changed files with 377 additions and 373 deletions

View File

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

View File

@ -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()
{

View File

@ -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];
}
}
}
/***********************************************************************************

View File

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

View 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__ */