diff options
author | 2018-11-03 10:21:04 +0100 | |
---|---|---|
committer | 2018-11-03 10:25:11 +0100 | |
commit | 4f5f5c6c92236a8d1948293bf5129117333f4152 (patch) | |
tree | e627882fb4ff816959deb755231c7c52b2a6f25d /src/devices | |
parent | cbd7b12f60d615cf9c4a554dab7326d38557df42 (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.cpp | 211 | ||||
-rw-r--r-- | src/devices/cpu/i386/i386priv.h | 206 | ||||
-rw-r--r-- | src/devices/cpu/i386/x87ops.hxx | 163 | ||||
-rw-r--r-- | src/devices/cpu/i386/x87priv.h | 169 |
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__ */ |