diff options
Diffstat (limited to 'src/osd/eminline.h')
-rw-r--r-- | src/osd/eminline.h | 227 |
1 files changed, 172 insertions, 55 deletions
diff --git a/src/osd/eminline.h b/src/osd/eminline.h index eb8ffaa9748..6d54a21a45f 100644 --- a/src/osd/eminline.h +++ b/src/osd/eminline.h @@ -25,22 +25,22 @@ #include "eigccx86.h" #elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__) #include "eigccppc.h" -#else -#error "no matching assembler implementations found - please compile with NOASM=1" +#elif defined(__arm__) || defined(__aarch64__) +#include "eigccarm.h" #endif +#include "eigcc.h" + #elif defined(_MSC_VER) -#if (defined(_M_IX86) || defined(_M_X64)) +#if defined(_M_IX86) || defined(_M_X64) #include "eivcx86.h" +#elif defined(_M_ARM) || defined(_M_ARM64) +#include "eivcarm.h" #endif #include "eivc.h" -#else - -#error "no matching assembler implementations found - please compile with NOASM=1" - #endif #endif // !defined(MAME_NOASM) @@ -56,7 +56,7 @@ -------------------------------------------------*/ #ifndef mul_32x32 -inline int64_t mul_32x32(int32_t a, int32_t b) +constexpr int64_t mul_32x32(int32_t a, int32_t b) { return int64_t(a) * int64_t(b); } @@ -70,7 +70,7 @@ inline int64_t mul_32x32(int32_t a, int32_t b) -------------------------------------------------*/ #ifndef mulu_32x32 -inline uint64_t mulu_32x32(uint32_t a, uint32_t b) +constexpr uint64_t mulu_32x32(uint32_t a, uint32_t b) { return uint64_t(a) * uint64_t(b); } @@ -84,7 +84,7 @@ inline uint64_t mulu_32x32(uint32_t a, uint32_t b) -------------------------------------------------*/ #ifndef mul_32x32_hi -inline int32_t mul_32x32_hi(int32_t a, int32_t b) +constexpr int32_t mul_32x32_hi(int32_t a, int32_t b) { return uint32_t((int64_t(a) * int64_t(b)) >> 32); } @@ -98,7 +98,7 @@ inline int32_t mul_32x32_hi(int32_t a, int32_t b) -------------------------------------------------*/ #ifndef mulu_32x32_hi -inline uint32_t mulu_32x32_hi(uint32_t a, uint32_t b) +constexpr uint32_t mulu_32x32_hi(uint32_t a, uint32_t b) { return uint32_t((uint64_t(a) * uint64_t(b)) >> 32); } @@ -113,7 +113,7 @@ inline uint32_t mulu_32x32_hi(uint32_t a, uint32_t b) -------------------------------------------------*/ #ifndef mul_32x32_shift -inline int32_t mul_32x32_shift(int32_t a, int32_t b, uint8_t shift) +constexpr int32_t mul_32x32_shift(int32_t a, int32_t b, uint8_t shift) { return int32_t((int64_t(a) * int64_t(b)) >> shift); } @@ -128,7 +128,7 @@ inline int32_t mul_32x32_shift(int32_t a, int32_t b, uint8_t shift) -------------------------------------------------*/ #ifndef mulu_32x32_shift -inline uint32_t mulu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) +constexpr uint32_t mulu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) { return uint32_t((uint64_t(a) * uint64_t(b)) >> shift); } @@ -141,7 +141,7 @@ inline uint32_t mulu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) -------------------------------------------------*/ #ifndef div_64x32 -inline int32_t div_64x32(int64_t a, int32_t b) +constexpr int32_t div_64x32(int64_t a, int32_t b) { return a / int64_t(b); } @@ -154,7 +154,7 @@ inline int32_t div_64x32(int64_t a, int32_t b) -------------------------------------------------*/ #ifndef divu_64x32 -inline uint32_t divu_64x32(uint64_t a, uint32_t b) +constexpr uint32_t divu_64x32(uint64_t a, uint32_t b) { return a / uint64_t(b); } @@ -168,10 +168,10 @@ inline uint32_t divu_64x32(uint64_t a, uint32_t b) -------------------------------------------------*/ #ifndef div_64x32_rem -inline int32_t div_64x32_rem(int64_t a, int32_t b, int32_t *remainder) +inline int32_t div_64x32_rem(int64_t a, int32_t b, int32_t &remainder) { - int32_t const res = div_64x32(a, b); - *remainder = a - (int64_t(b) * res); + int32_t const res(div_64x32(a, b)); + remainder = a - (int64_t(b) * res); return res; } #endif @@ -184,10 +184,10 @@ inline int32_t div_64x32_rem(int64_t a, int32_t b, int32_t *remainder) -------------------------------------------------*/ #ifndef divu_64x32_rem -inline uint32_t divu_64x32_rem(uint64_t a, uint32_t b, uint32_t *remainder) +inline uint32_t divu_64x32_rem(uint64_t a, uint32_t b, uint32_t &remainder) { - uint32_t const res = divu_64x32(a, b); - *remainder = a - (uint64_t(b) * res); + uint32_t const res(divu_64x32(a, b)); + remainder = a - (uint64_t(b) * res); return res; } #endif @@ -200,7 +200,7 @@ inline uint32_t divu_64x32_rem(uint64_t a, uint32_t b, uint32_t *remainder) -------------------------------------------------*/ #ifndef div_32x32_shift -inline int32_t div_32x32_shift(int32_t a, int32_t b, uint8_t shift) +constexpr int32_t div_32x32_shift(int32_t a, int32_t b, uint8_t shift) { return (int64_t(a) << shift) / int64_t(b); } @@ -214,7 +214,7 @@ inline int32_t div_32x32_shift(int32_t a, int32_t b, uint8_t shift) -------------------------------------------------*/ #ifndef divu_32x32_shift -inline uint32_t divu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) +constexpr uint32_t divu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) { return (uint64_t(a) << shift) / uint64_t(b); } @@ -227,7 +227,7 @@ inline uint32_t divu_32x32_shift(uint32_t a, uint32_t b, uint8_t shift) -------------------------------------------------*/ #ifndef mod_64x32 -inline int32_t mod_64x32(int64_t a, int32_t b) +constexpr int32_t mod_64x32(int64_t a, int32_t b) { return a - (b * div_64x32(a, b)); } @@ -240,7 +240,7 @@ inline int32_t mod_64x32(int64_t a, int32_t b) -------------------------------------------------*/ #ifndef modu_64x32 -inline uint32_t modu_64x32(uint64_t a, uint32_t b) +constexpr uint32_t modu_64x32(uint64_t a, uint32_t b) { return a - (b * divu_64x32(a, b)); } @@ -253,7 +253,7 @@ inline uint32_t modu_64x32(uint64_t a, uint32_t b) -------------------------------------------------*/ #ifndef recip_approx -inline float recip_approx(float value) +constexpr float recip_approx(float value) { return 1.0f / value; } @@ -266,7 +266,7 @@ inline float recip_approx(float value) -------------------------------------------------*/ #ifndef mul_64x64 -inline int64_t mul_64x64(int64_t a, int64_t b, int64_t *hi) +inline int64_t mul_64x64(int64_t a, int64_t b, int64_t &hi) { uint64_t const a_hi = uint64_t(a) >> 32; uint64_t const b_hi = uint64_t(b) >> 32; @@ -279,13 +279,13 @@ inline int64_t mul_64x64(int64_t a, int64_t b, int64_t *hi) uint64_t const ab_hi = a_hi * b_hi; uint64_t const carry = ((ab_lo >> 32) + uint32_t(ab_m1) + uint32_t(ab_m2)) >> 32; - *hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry; + hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry; // adjust for sign if (a < 0) - *hi -= b; + hi -= b; if (b < 0) - *hi -= a; + hi -= a; return ab_lo + (ab_m1 << 32) + (ab_m2 << 32); } @@ -298,7 +298,7 @@ inline int64_t mul_64x64(int64_t a, int64_t b, int64_t *hi) -------------------------------------------------*/ #ifndef mulu_64x64 -inline uint64_t mulu_64x64(uint64_t a, uint64_t b, uint64_t *hi) +inline uint64_t mulu_64x64(uint64_t a, uint64_t b, uint64_t &hi) { uint64_t const a_hi = uint32_t(a >> 32); uint64_t const b_hi = uint32_t(b >> 32); @@ -311,25 +311,55 @@ inline uint64_t mulu_64x64(uint64_t a, uint64_t b, uint64_t *hi) uint64_t const ab_hi = a_hi * b_hi; uint64_t const carry = ((ab_lo >> 32) + uint32_t(ab_m1) + uint32_t(ab_m2)) >> 32; - *hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry; + hi = ab_hi + (ab_m1 >> 32) + (ab_m2 >> 32) + carry; return ab_lo + (ab_m1 << 32) + (ab_m2 << 32); } #endif +/*------------------------------------------------- + addu_32x32_co - perform an unsigned 32 bit + 32 + bit addition and return the result with carry + out +-------------------------------------------------*/ + +#ifndef addu_32x32_co +inline bool addu_32x32_co(uint32_t a, uint32_t b, uint32_t &sum) +{ + sum = a + b; + return (a > sum) || (b > sum); +} +#endif + + +/*------------------------------------------------- + addu_64x64_co - perform an unsigned 64 bit + 64 + bit addition and return the result with carry + out +-------------------------------------------------*/ + +#ifndef addu_64x64_co +inline bool addu_64x64_co(uint64_t a, uint64_t b, uint64_t &sum) +{ + sum = a + b; + return (a > sum) || (b > sum); +} +#endif + + /*************************************************************************** INLINE BIT MANIPULATION FUNCTIONS ***************************************************************************/ /*------------------------------------------------- - count_leading_zeros - return the number of + count_leading_zeros_32 - return the number of leading zero bits in a 32-bit value -------------------------------------------------*/ -#ifndef count_leading_zeros -inline uint8_t count_leading_zeros(uint32_t val) +#ifndef count_leading_zeros_32 +inline uint8_t count_leading_zeros_32(uint32_t val) { if (!val) return 32U; uint8_t count; @@ -340,12 +370,12 @@ inline uint8_t count_leading_zeros(uint32_t val) /*------------------------------------------------- - count_leading_ones - return the number of + count_leading_ones_32 - return the number of leading one bits in a 32-bit value -------------------------------------------------*/ -#ifndef count_leading_ones -inline uint8_t count_leading_ones(uint32_t val) +#ifndef count_leading_ones_32 +inline uint8_t count_leading_ones_32(uint32_t val) { uint8_t count; for (count = 0; int32_t(val) < 0; count++) val <<= 1; @@ -355,22 +385,48 @@ inline uint8_t count_leading_ones(uint32_t val) /*------------------------------------------------- + count_leading_zeros_64 - return the number of + leading zero bits in a 64-bit value +-------------------------------------------------*/ + +#ifndef count_leading_zeros_64 +inline uint8_t count_leading_zeros_64(uint64_t val) +{ + if (!val) return 64U; + uint8_t count; + for (count = 0; int64_t(val) >= 0; count++) val <<= 1; + return count; +} +#endif + + +/*------------------------------------------------- + count_leading_ones_64 - return the number of + leading one bits in a 64-bit value +-------------------------------------------------*/ + +#ifndef count_leading_ones_64 +inline uint8_t count_leading_ones_64(uint64_t val) +{ + uint8_t count; + for (count = 0; int64_t(val) < 0; count++) val <<= 1; + return count; +} +#endif + + +/*------------------------------------------------- population_count_32 - return the number of one bits in a 32-bit value -------------------------------------------------*/ #ifndef population_count_32 -#if defined(__NetBSD__) -#define population_count_32 popcount32 -#else inline unsigned population_count_32(uint32_t val) { -#if defined(__GNUC__) - // uses CPU feature if available, otherwise falls back to implementation similar to what follows - static_assert(sizeof(val) == sizeof(unsigned), "expected 32-bit unsigned int"); - return unsigned(__builtin_popcount(static_cast<unsigned>(val))); +#if defined(__NetBSD__) + return popcount32(val); #else - // optimal Hamming weight assuing fast 32*32->32 + // optimal Hamming weight assuming fast 32*32->32 constexpr uint32_t m1(0x55555555); constexpr uint32_t m2(0x33333333); constexpr uint32_t m4(0x0f0f0f0f); @@ -382,7 +438,6 @@ inline unsigned population_count_32(uint32_t val) #endif } #endif -#endif /*------------------------------------------------- @@ -391,15 +446,10 @@ inline unsigned population_count_32(uint32_t val) -------------------------------------------------*/ #ifndef population_count_64 -#if defined(__NetBSD__) -#define population_count_64 popcount64 -#else inline unsigned population_count_64(uint64_t val) { -#if defined(__GNUC__) - // uses CPU feature if available, otherwise falls back to implementation similar to what follows - static_assert(sizeof(val) == sizeof(unsigned long long), "expected 64-bit unsigned long long int"); - return unsigned(__builtin_popcountll(static_cast<unsigned long long>(val))); +#if defined(__NetBSD__) + return popcount64(val); #else // guess that architectures with 64-bit pointers have 64-bit multiplier if (sizeof(void *) >= sizeof(uint64_t)) @@ -422,6 +472,73 @@ inline unsigned population_count_64(uint64_t val) #endif } #endif + + +/*------------------------------------------------- + rotl_32 - circularly shift a 32-bit value left + by the specified number of bits (modulo 32) +-------------------------------------------------*/ + +#ifndef rotl_32 +constexpr uint32_t rotl_32(uint32_t val, int shift) +{ + shift &= 31; + if (shift) + return val << shift | val >> (32 - shift); + else + return val; +} +#endif + + +/*------------------------------------------------- + rotr_32 - circularly shift a 32-bit value right + by the specified number of bits (modulo 32) +-------------------------------------------------*/ + +#ifndef rotr_32 +constexpr uint32_t rotr_32(uint32_t val, int shift) +{ + shift &= 31; + if (shift) + return val >> shift | val << (32 - shift); + else + return val; +} +#endif + + +/*------------------------------------------------- + rotl_64 - circularly shift a 64-bit value left + by the specified number of bits (modulo 64) +-------------------------------------------------*/ + +#ifndef rotl_64 +constexpr uint64_t rotl_64(uint64_t val, int shift) +{ + shift &= 63; + if (shift) + return val << shift | val >> (64 - shift); + else + return val; +} +#endif + + +/*------------------------------------------------- + rotr_64 - circularly shift a 64-bit value right + by the specified number of bits (modulo 64) +-------------------------------------------------*/ + +#ifndef rotr_64 +constexpr uint64_t rotr_64(uint64_t val, int shift) +{ + shift &= 63; + if (shift) + return val >> shift | val << (64 - shift); + else + return val; +} #endif @@ -437,7 +554,7 @@ inline unsigned population_count_64(uint64_t val) -------------------------------------------------*/ #ifndef get_profile_ticks -inline int64_t get_profile_ticks() +inline int64_t get_profile_ticks() noexcept { return osd_ticks(); } |