summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/devices/machine/netlist.cpp8
-rw-r--r--src/lib/netlist/nl_config.h9
-rw-r--r--src/lib/netlist/nltypes.h8
-rw-r--r--src/lib/netlist/plib/pconfig.h13
-rw-r--r--src/lib/netlist/plib/pexception.cpp26
-rw-r--r--src/lib/netlist/plib/ptypes.h42
6 files changed, 69 insertions, 37 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index e26ac9b2764..9fd71f0bc3c 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -802,14 +802,12 @@ struct save_helper
m_device->save_item(item, (m_prefix + "_" + name).c_str());
}
-#if PHAS_INT128
- void save_item(INT128 &item, pstring name)
+ void save_item(std::enable_if_t<plib::compile_info::has_int128::value,INT128> &item, pstring name)
{
auto *p = reinterpret_cast<std::uint64_t *>(&item);
m_device->save_item(p[0], (m_prefix + "_" + name + "_1").c_str());
m_device->save_item(p[1], (m_prefix + "_" + name + "_2").c_str());
}
-#endif
private:
device_t *m_device;
@@ -1133,10 +1131,8 @@ void netlist_mame_device::save_state()
save_pointer((int16_t *) s->ptr(), s->name().c_str(), s->count());
else if (s->dt().size() == sizeof(int8_t))
save_pointer((int8_t *) s->ptr(), s->name().c_str(), s->count());
-#if (PHAS_INT128)
- else if (s->dt().size() == sizeof(INT128))
+ else if (plib::compile_info::has_int128::value && s->dt().size() == sizeof(INT128))
save_pointer((int64_t *) s->ptr(), s->name().c_str(), s->count() * 2);
-#endif
else
netlist().log().fatal("Unknown integral type size {1} for {2}\n", s->dt().size(), s->name().c_str());
}
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 9f122502efa..8740b5ddbd9 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -115,6 +115,15 @@
#define NL_USE_FLOAT128 PUSE_FLOAT128
#endif
+/// \brief Prefer 128bit int type for ptime if supported
+///
+/// Set this to one if you want to use 128 bit int for ptime.
+/// This is about 10% slower on a skylake processor for pongf.
+///
+#ifndef NL_PREFER_INT128
+#define NL_PREFER_INT128 (0)
+#endif
+
/// \brief Support float type for matrix calculations.
///
/// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times
diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h
index fe0ec07067d..f7ccb9b53ec 100644
--- a/src/lib/netlist/nltypes.h
+++ b/src/lib/netlist/nltypes.h
@@ -142,13 +142,9 @@ namespace netlist
} // namespace detail
-#if (PHAS_INT128)
using netlist_time = plib::ptime<std::int64_t, config::INTERNAL_RES::value>;
- using netlist_time_ext = plib::ptime<INT128, config::INTERNAL_RES::value>;
-#else
- using netlist_time = plib::ptime<std::int64_t, config::INTERNAL_RES::value>;
- using netlist_time_ext = netlist_time;
-#endif
+ using netlist_time_ext = plib::ptime<std::conditional<NL_PREFER_INT128 && plib::compile_info::has_int128::value, INT128, std::int64_t>::type, config::INTERNAL_RES::value>;
+
static_assert(noexcept(netlist_time::from_nsec(1)), "Not evaluated as constexpr");
//============================================================
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 4e116b90344..b719139d73f 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -22,15 +22,6 @@
#define PUSE_ACCURATE_STATS (0)
#endif
-/// \brief System supports INT128
-///
-/// Set this to one if you want to use 128 bit int for ptime.
-/// This is about 10% slower on a skylake processor for pongf.
-///
-#ifndef PHAS_INT128
-#define PHAS_INT128 (0)
-#endif
-
/// \brief Add support for the __float128 floating point type.
///
#ifndef PUSE_FLOAT128
@@ -137,10 +128,6 @@
#endif
#endif
-#if (PHAS_INT128)
-typedef __uint128_t UINT128;
-typedef __int128_t INT128;
-#endif
#if (PUSE_FLOAT128)
typedef __float128 FLOAT128;
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index 674601f2ed8..d332f989321 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -6,6 +6,7 @@
#include <cfenv>
#include <iostream>
+#include <cfloat>
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
#define HAS_FEENABLE_EXCEPT (1)
@@ -103,6 +104,8 @@ namespace plib {
bool fpsignalenabler::m_enable = false;
+ //FIXME: mingw needs to be compiled with "-fnon-call-exceptions"
+
fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
{
#if HAS_FEENABLE_EXCEPT
@@ -116,6 +119,18 @@ namespace plib {
if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
m_last_enabled = feenableexcept(b);
}
+ #elif defined(_WIN32) && defined(_EM_INEXACT)
+ if (m_enable)
+ {
+ int b = _EM_DENORMAL | _EM_INEXACT | _EM_ZERODIVIDE | _EM_UNDERFLOW | _EM_OVERFLOW | _EM_INVALID;
+ if (fpexceptions & plib::FP_INEXACT) b &= ~_EM_INEXACT;
+ if (fpexceptions & plib::FP_DIVBYZERO) b &= ~_EM_ZERODIVIDE;
+ if (fpexceptions & plib::FP_UNDERFLOW) b &= ~_EM_UNDERFLOW;
+ if (fpexceptions & plib::FP_OVERFLOW) b &= ~_EM_OVERFLOW;
+ if (fpexceptions & plib::FP_INVALID) b &= ~_EM_INVALID;
+ m_last_enabled = _controlfp(0, 0);
+ _controlfp(b, _MCW_EM );
+ }
#else
m_last_enabled = 0;
#endif
@@ -130,12 +145,23 @@ namespace plib {
fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
}
+ #elif defined(_WIN32) && defined(_EM_INEXACT)
+ if (m_enable)
+ {
+ _controlfp(m_last_enabled, _MCW_EM);
+ }
#endif
}
bool fpsignalenabler::supported()
{
+ #if HAS_FEENABLE_EXCEPT
+ return true;
+ #elif defined(_WIN32) && defined(_EM_INEXACT)
return true;
+ #else
+ return false;
+ #endif
}
bool fpsignalenabler::global_enable(bool enable)
diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h
index fa2172c7507..c40735a0f48 100644
--- a/src/lib/netlist/plib/ptypes.h
+++ b/src/lib/netlist/plib/ptypes.h
@@ -39,6 +39,10 @@ namespace plib
// compile time information
//============================================================
+ /// \brief Dummy 128 bit types for platforms which don't support 128 bit
+ struct UINT128_DUMMY {};
+ struct INT128_DUMMY {};
+
struct compile_info
{
#ifdef _WIN32
@@ -52,7 +56,27 @@ namespace plib
using win32 = std::integral_constant<bool, false>;
using unicode = std::integral_constant<bool, true>;
#endif
+ #ifdef __SIZEOF_INT128__
+ using has_int128 = std::integral_constant<bool, true>;
+ using int128_type = __int128_t;
+ using uint128_type = __uint128_t;
+ static constexpr int128_type int128_max() { return (~static_cast<uint128_type>(0)) >> 1; }
+ static constexpr uint128_type uint128_max() { return ~(static_cast<uint128_type>(0)); }
+ #else
+ using has_int128 = std::integral_constant<bool, false>;
+ using int128_type = INT128_DUMMY;
+ using uint128_type = UINT128_DUMMY;
+ static constexpr int128_type int128_max() { return int128_type(); }
+ static constexpr uint128_type uint128_max() { return uint128_type(); }
+ #endif
};
+} // namespace plib
+
+using INT128 = plib::compile_info::int128_type;
+using UINT128 = plib::compile_info::uint128_type;
+
+namespace plib
+{
template<typename T> struct is_integral : public std::is_integral<T> { };
template<typename T> struct is_signed : public std::is_signed<T> { };
@@ -60,7 +84,7 @@ namespace plib
template<typename T> struct numeric_limits : public std::numeric_limits<T> { };
// 128 bit support at least on GCC is not fully supported
-#if PHAS_INT128
+
template<> struct is_integral<UINT128> { static constexpr bool value = true; };
template<> struct is_integral<INT128> { static constexpr bool value = true; };
@@ -74,17 +98,16 @@ namespace plib
{
static constexpr UINT128 max() noexcept
{
- return ~(static_cast<UINT128>(0));
+ return compile_info::uint128_max();
}
};
template<> struct numeric_limits<INT128>
{
static constexpr INT128 max() noexcept
{
- return (~static_cast<UINT128>(0)) >> 1;
+ return compile_info::int128_max();
}
};
-#endif
template<typename T> struct is_floating_point : public std::is_floating_point<T> { };
@@ -110,16 +133,13 @@ namespace plib
template<unsigned bits>
struct size_for_bits
{
+ static_assert(bits <= 64 || (bits <= 128 && compile_info::has_int128::value), "not supported");
enum { value =
bits <= 8 ? 1 :
bits <= 16 ? 2 :
bits <= 32 ? 4 :
-#if (PHAS_INT128)
bits <= 64 ? 8 :
16
-#else
- 8
-#endif
};
};
@@ -128,9 +148,7 @@ namespace plib
template<> struct least_type_for_size<2> { using type = uint_least16_t; };
template<> struct least_type_for_size<4> { using type = uint_least32_t; };
template<> struct least_type_for_size<8> { using type = uint_least64_t; };
-#if (PHAS_INT128)
template<> struct least_type_for_size<16> { using type = UINT128; };
-#endif
// This is different to the standard library. Mappings provided in stdint
// are not always fastest.
@@ -139,19 +157,19 @@ namespace plib
template<> struct fast_type_for_size<2> { using type = uint32_t; };
template<> struct fast_type_for_size<4> { using type = uint32_t; };
template<> struct fast_type_for_size<8> { using type = uint_fast64_t; };
-#if (PHAS_INT128)
template<> struct fast_type_for_size<16> { using type = UINT128; };
-#endif
template<unsigned bits>
struct least_type_for_bits
{
+ static_assert(bits <= 64 || (bits <= 128 && compile_info::has_int128::value), "not supported");
using type = typename least_type_for_size<size_for_bits<bits>::value>::type;
};
template<unsigned bits>
struct fast_type_for_bits
{
+ static_assert(bits <= 64 || (bits <= 128 && compile_info::has_int128::value), "not supported");
using type = typename fast_type_for_size<size_for_bits<bits>::value>::type;
};