summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author yz70s <yz70s@users.noreply.github.com>2018-11-03 10:21:04 +0100
committer yz70s <yz70s@users.noreply.github.com>2018-11-03 10:25:11 +0100
commit4f5f5c6c92236a8d1948293bf5129117333f4152 (patch)
treee627882fb4ff816959deb755231c7c52b2a6f25d /src/devices
parentcbd7b12f60d615cf9c4a554dab7326d38557df42 (diff)
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
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/i386/i386.cpp211
-rw-r--r--src/devices/cpu/i386/i386priv.h206
-rw-r--r--src/devices/cpu/i386/x87ops.hxx163
-rw-r--r--src/devices/cpu/i386/x87priv.h169
4 files changed, 376 insertions, 373 deletions
diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp
index 9952755dc22..8d9617507e1 100644
--- a/src/devices/cpu/i386/i386.cpp
+++ b/src/devices/cpu/i386/i386.cpp
@@ -20,10 +20,12 @@
#include "emu.h"
#include "i386.h"
-
-#include "debugger.h"
#include "i386priv.h"
+#include "x87priv.h"
+#include "cycles.h"
+#include "i386ops.h"
+#include "debugger.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()
{
diff --git a/src/devices/cpu/i386/i386priv.h b/src/devices/cpu/i386/i386priv.h
index 1e5439f205f..954e49ee6c7 100644
--- a/src/devices/cpu/i386/i386priv.h
+++ b/src/devices/cpu/i386/i386priv.h
@@ -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];
+ }
+ }
+}
+
/***********************************************************************************
diff --git a/src/devices/cpu/i386/x87ops.hxx b/src/devices/cpu/i386/x87ops.hxx
index 4c58719b88b..a50db982b36 100644
--- a/src/devices/cpu/i386/x87ops.hxx
+++ b/src/devices/cpu/i386/x87ops.hxx
@@ -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
diff --git a/src/devices/cpu/i386/x87priv.h b/src/devices/cpu/i386/x87priv.h
new file mode 100644
index 00000000000..67cf067a15f
--- /dev/null
+++ b/src/devices/cpu/i386/x87priv.h
@@ -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__ */