summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-06-12 03:00:21 +1000
committer Vas Crabb <cuavas@users.noreply.github.com>2021-06-13 09:38:01 +1000
commit73d97b7dc492871d3dcf4ee919fc443dd2308dec (patch)
treec394cccb9d6514a5b8e69f054d5d27ecc50a5d58 /src/osd
parent27b93b23486533747d9ba185ff54da860223a463 (diff)
Added helpers for 64-bit count leading zeroes/ones.
Diffstat (limited to 'src/osd')
-rw-r--r--src/osd/eigcc.h56
-rw-r--r--src/osd/eigccarm.h62
-rw-r--r--src/osd/eigccppc.h62
-rw-r--r--src/osd/eigccx86.h64
-rw-r--r--src/osd/eivc.h57
-rw-r--r--src/osd/eivcarm.h75
-rw-r--r--src/osd/eminline.h47
7 files changed, 384 insertions, 39 deletions
diff --git a/src/osd/eigcc.h b/src/osd/eigcc.h
index 69bbeffde07..bad168a8390 100644
--- a/src/osd/eigcc.h
+++ b/src/osd/eigcc.h
@@ -55,6 +55,62 @@ inline bool _addu_64x64_co(uint64_t a, uint64_t b, uint64_t &sum)
***************************************************************************/
/*-------------------------------------------------
+ count_leading_zeros_32 - return the number of
+ leading zero bits in a 32-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_zeros_32
+inline uint8_t count_leading_zeros_32(uint32_t val)
+{
+ // uses CPU feature if available, otherwise falls back to runtime library call
+ static_assert(sizeof(val) == sizeof(unsigned), "expected 32-bit unsigned int");
+ return uint8_t(unsigned(val ? __builtin_clz(val) : 32));
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones_32 - return the number of
+ leading one bits in a 32-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_ones_32
+inline uint8_t count_leading_ones_32(uint32_t val)
+{
+ return count_leading_zeros_32(~val);
+}
+#endif
+
+
+/*-------------------------------------------------
+ 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)
+{
+ // uses CPU feature if available, otherwise falls back to runtime library call
+ static_assert(sizeof(val) == sizeof(unsigned long long), "expected 64-bit unsigned long long int");
+ return uint8_t(unsigned(val ? __builtin_clzll(val) : 64));
+}
+#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)
+{
+ return count_leading_zeros_64(~val);
+}
+#endif
+
+
+/*-------------------------------------------------
population_count_32 - return the number of
one bits in a 32-bit value
-------------------------------------------------*/
diff --git a/src/osd/eigccarm.h b/src/osd/eigccarm.h
index 27d79c4a5c6..90004daf9d4 100644
--- a/src/osd/eigccarm.h
+++ b/src/osd/eigccarm.h
@@ -239,14 +239,14 @@ _mulu_64x64(uint64_t a, uint64_t b, uint64_t &hi)
***************************************************************************/
/*-------------------------------------------------
- count_leading_zeros - return the number of
+ count_leading_zeros_32 - return the number of
leading zero bits in a 32-bit value
-------------------------------------------------*/
#if defined(__aarch64__)
-#define count_leading_zeros _count_leading_zeros
+#define count_leading_zeros_32 _count_leading_zeros_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_zeros(uint32_t value)
+_count_leading_zeros_32(uint32_t value)
{
uint32_t result;
@@ -256,20 +256,20 @@ _count_leading_zeros(uint32_t value)
: [value] "r" (value)
);
- return result;
+ return uint8_t(result);
}
#endif
/*-------------------------------------------------
- count_leading_ones - return the number of
+ count_leading_ones_32 - return the number of
leading one bits in a 32-bit value
-------------------------------------------------*/
#if defined(__aarch64__)
-#define count_leading_ones _count_leading_ones
+#define count_leading_ones_32 _count_leading_ones_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_ones(uint32_t value)
+_count_leading_ones_32(uint32_t value)
{
uint32_t result;
@@ -279,7 +279,53 @@ _count_leading_ones(uint32_t value)
: [value] "r" (~value)
);
- return result;
+ return uint8_t(result);
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_zeros_64 - return the number of
+ leading zero bits in a 64-bit value
+-------------------------------------------------*/
+
+#if defined(__aarch64__)
+#define count_leading_zeros_64 _count_leading_zeros_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_zeros_64(uint64_t value)
+{
+ uint64_t result;
+
+ __asm__ (
+ " clz %[result], %[value] \n"
+ : [result] "=r" (result)
+ : [value] "r" (value)
+ );
+
+ return uint8_t(result);
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones_64 - return the number of
+ leading one bits in a 64-bit value
+-------------------------------------------------*/
+
+#if defined(__aarch64__)
+#define count_leading_ones_64 _count_leading_ones_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_ones_64(uint64_t value)
+{
+ uint64_t result;
+
+ __asm__ (
+ " clz %[result], %[value] \n"
+ : [result] "=r" (result)
+ : [value] "r" (~value)
+ );
+
+ return uint8_t(result);
}
#endif
diff --git a/src/osd/eigccppc.h b/src/osd/eigccppc.h
index 3a1b2093d4e..de1372ff39b 100644
--- a/src/osd/eigccppc.h
+++ b/src/osd/eigccppc.h
@@ -239,13 +239,13 @@ _mulu_64x64(uint64_t a, uint64_t b, uint64_t &hi)
***************************************************************************/
/*-------------------------------------------------
- count_leading_zeros - return the number of
+ count_leading_zeros_32 - return the number of
leading zero bits in a 32-bit value
-------------------------------------------------*/
-#define count_leading_zeros _count_leading_zeros
+#define count_leading_zeros_32 _count_leading_zeros_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_zeros(uint32_t value)
+_count_leading_zeros_32(uint32_t value)
{
uint32_t result;
@@ -255,18 +255,18 @@ _count_leading_zeros(uint32_t value)
: [value] "r" (value)
);
- return result;
+ return uint8_t(result);
}
/*-------------------------------------------------
- count_leading_ones - return the number of
+ count_leading_ones_32 - return the number of
leading one bits in a 32-bit value
-------------------------------------------------*/
-#define count_leading_ones _count_leading_ones
+#define count_leading_ones_32 _count_leading_ones_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_ones(uint32_t value)
+_count_leading_ones_32(uint32_t value)
{
uint32_t result;
@@ -276,7 +276,53 @@ _count_leading_ones(uint32_t value)
: [value] "r" (~value)
);
- return result;
+ return uint8_t(result);
+}
+
+
+/*-------------------------------------------------
+ count_leading_zeros_64 - return the number of
+ leading zero bits in a 64-bit value
+-------------------------------------------------*/
+
+#if defined(__ppc64__)
+#define count_leading_zeros_64 _count_leading_zeros_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_zeros_64(uint64_t value)
+{
+ uint64_t result;
+
+ __asm__ (
+ " cntlzd %[result], %[value] \n"
+ : [result] "=r" (result)
+ : [value] "r" (value)
+ );
+
+ return uint8_t(result);
}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones_64 - return the number of
+ leading one bits in a 64-bit value
+-------------------------------------------------*/
+
+#if defined(__ppc64__)
+#define count_leading_ones_64 _count_leading_ones_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_ones_64(uint64_t value)
+{
+ uint64_t result;
+
+ __asm__ (
+ " cntlzd %[result], %[value] \n"
+ : [result] "=r" (result)
+ : [value] "r" (~value)
+ );
+
+ return uint8_t(result);
+}
+#endif
#endif // MAME_OSD_EIGCCPPC_H
diff --git a/src/osd/eigccx86.h b/src/osd/eigccx86.h
index b3bbf7bd0ec..35f02e12f5e 100644
--- a/src/osd/eigccx86.h
+++ b/src/osd/eigccx86.h
@@ -433,13 +433,13 @@ _mulu_64x64(uint64_t a, uint64_t b, uint64_t &hi)
***************************************************************************/
/*-------------------------------------------------
- count_leading_zeros - return the number of
+ count_leading_zeros_32 - return the number of
leading zero bits in a 32-bit value
-------------------------------------------------*/
-#define count_leading_zeros _count_leading_zeros
+#define count_leading_zeros_32 _count_leading_zeros_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_zeros(uint32_t value)
+_count_leading_zeros_32(uint32_t value)
{
uint32_t result;
__asm__ (
@@ -450,18 +450,18 @@ _count_leading_zeros(uint32_t value)
, [bias] "rm" (~uint32_t(0)) // 'bias' can be register or memory
: "cc" // clobbers condition codes
);
- return 31U - result;
+ return uint8_t(31U - result);
}
/*-------------------------------------------------
- count_leading_ones - return the number of
+ count_leading_ones_32 - return the number of
leading one bits in a 32-bit value
-------------------------------------------------*/
-#define count_leading_ones _count_leading_ones
+#define count_leading_ones_32 _count_leading_ones_32
inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
-_count_leading_ones(uint32_t value)
+_count_leading_ones_32(uint32_t value)
{
uint32_t result;
__asm__ (
@@ -472,7 +472,55 @@ _count_leading_ones(uint32_t value)
, [bias] "rm" (~uint32_t(0)) // 'bias' can be register or memory
: "cc" // clobbers condition codes
);
- return 31U - result;
+ return uint8_t(31U - result);
}
+
+/*-------------------------------------------------
+ count_leading_zeros_64 - return the number of
+ leading zero bits in a 64-bit value
+-------------------------------------------------*/
+
+#ifdef __x86_64__
+#define count_leading_zeros_64 _count_leading_zeros_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_zeros_64(uint64_t value)
+{
+ uint64_t result;
+ __asm__ (
+ " bsrq %[value], %[result] ;"
+ " cmovzq %[bias], %[result] ;"
+ : [result] "=&r" (result) // result can be in any register
+ : [value] "rm" (value) // 'value' can be register or memory
+ , [bias] "rm" (~uint64_t(0)) // 'bias' can be register or memory
+ : "cc" // clobbers condition codes
+ );
+ return uint8_t(63U - result);
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones_64 - return the number of
+ leading one bits in a 64-bit value
+-------------------------------------------------*/
+
+#ifdef __x86_64__
+#define count_leading_ones_64 _count_leading_ones_64
+inline uint8_t ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_ones_64(uint64_t value)
+{
+ uint64_t result;
+ __asm__ (
+ " bsrq %[value], %[result] ;"
+ " cmovzq %[bias], %[result] ;"
+ : [result] "=&r" (result) // result can be in any register
+ : [value] "rm" (~value) // 'value' can be register or memory
+ , [bias] "rm" (~uint64_t(0)) // 'bias' can be register or memory
+ : "cc" // clobbers condition codes
+ );
+ return uint8_t(63U - result);
+}
+#endif
+
#endif // MAME_OSD_EIGCCX86_H
diff --git a/src/osd/eivc.h b/src/osd/eivc.h
index 56d1dcc3ab8..2ffd0e7633b 100644
--- a/src/osd/eivc.h
+++ b/src/osd/eivc.h
@@ -15,6 +15,9 @@
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
+#ifdef PTR64
+#pragma intrinsic(_BitScanReverse64)
+#endif
/***************************************************************************
@@ -22,13 +25,13 @@
***************************************************************************/
/*-------------------------------------------------
- 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
-#define count_leading_zeros _count_leading_zeros
-__forceinline uint8_t _count_leading_zeros(uint32_t value)
+#ifndef count_leading_zeros_32
+#define count_leading_zeros_32 _count_leading_zeros_32
+__forceinline uint8_t _count_leading_zeros_32(uint32_t value)
{
unsigned long index;
return _BitScanReverse(&index, value) ? (31U - index) : 32U;
@@ -37,17 +40,55 @@ __forceinline uint8_t _count_leading_zeros(uint32_t value)
/*-------------------------------------------------
- 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
-#define count_leading_ones _count_leading_ones
-__forceinline uint8_t _count_leading_ones(uint32_t value)
+#ifndef count_leading_ones_32
+#define count_leading_ones_32 _count_leading_ones_32
+__forceinline uint8_t _count_leading_ones_32(uint32_t value)
{
unsigned long index;
return _BitScanReverse(&index, ~value) ? (31U - index) : 32U;
}
#endif
+
+/*-------------------------------------------------
+ count_leading_zeros_64 - return the number of
+ leading zero bits in a 64-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_zeros_64
+#define count_leading_zeros_64 _count_leading_zeros_64
+__forceinline uint8_t _count_leading_zeros_64(uint64_t value)
+{
+ unsigned long index;
+#ifdef PTR64
+ return _BitScanReverse64(&index, value) ? (63U - index) : 64U;
+#else
+ return _BitScanReverse(&index, uint32_t(value >> 32)) ? (31U - index) : _BitScanReverse(&index, uint32_t(value)) ? (63U - index) : 64U;
+#endif
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones_64 - return the number of
+ leading one bits in a 64-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_ones_64
+#define count_leading_ones_64 _count_leading_ones_64
+__forceinline uint8_t _count_leading_ones_64(uint64_t value)
+{
+ unsigned long index;
+#ifdef PTR64
+ return _BitScanReverse64(&index, ~value) ? (63U - index) : 64U;
+#else
+ return _BitScanReverse(&index, ~uint32_t(value >> 32)) ? (31U - index) : _BitScanReverse(&index, ~uint32_t(value)) ? (63U - index) : 64U;
+#endif
+}
+#endif
+
#endif // MAME_OSD_EIVC_H
diff --git a/src/osd/eivcarm.h b/src/osd/eivcarm.h
new file mode 100644
index 00000000000..5e612cb25fb
--- /dev/null
+++ b/src/osd/eivcarm.h
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+//============================================================
+//
+// eivcarm.h
+//
+// ARM/AArch64 inline implementations for MSVC compiler.
+//
+//============================================================
+
+#ifndef MAME_OSD_EIVCARM_H
+#define MAME_OSD_EIVCARM_H
+
+#pragma once
+
+#include <intrin.h>
+
+#pragma intrinsic(_CountLeadingZeros)
+#pragma intrinsic(_CountLeadingZeros64)
+#pragma intrinsic(_CountLeadingOnes)
+#pragma intrinsic(_CountLeadingOnes64)
+
+
+/***************************************************************************
+ INLINE BIT MANIPULATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ count_leading_zeros_32 - return the number of
+ leading zero bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_zeros_32 _count_leading_zeros_32
+__forceinline uint8_t _count_leading_zeros_32(uint32_t value)
+{
+ return uint8_t(_CountLeadingZeros(value));
+}
+
+
+/*-------------------------------------------------
+ count_leading_ones_32 - return the number of
+ leading one bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_ones_32 _count_leading_ones_32
+__forceinline uint8_t _count_leading_ones_32(uint32_t value)
+{
+ return uint8_t(_CountLeadingOnes(value));
+}
+
+
+/*-------------------------------------------------
+ count_leading_zeros_64 - return the number of
+ leading zero bits in a 64-bit value
+-------------------------------------------------*/
+
+#define count_leading_zeros_64 _count_leading_zeros_64
+__forceinline uint8_t _count_leading_zeros_64(uint64_t value)
+{
+ return uint8_t(_CountLeadingZeros64(value));
+}
+
+
+/*-------------------------------------------------
+ count_leading_ones_64 - return the number of
+ leading one bits in a 64-bit value
+-------------------------------------------------*/
+
+#define count_leading_ones_64 _count_leading_ones_64
+__forceinline uint8_t _count_leading_ones_64(uint64_t value)
+{
+ return uint8_t(_CountLeadingOnes64(value));
+}
+
+#endif // MAME_OSD_EIVCARM_H
diff --git a/src/osd/eminline.h b/src/osd/eminline.h
index a7cc4cfee3d..02bd22b3fdb 100644
--- a/src/osd/eminline.h
+++ b/src/osd/eminline.h
@@ -33,8 +33,10 @@
#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"
@@ -352,12 +354,12 @@ inline bool addu_64x64_co(uint64_t a, uint64_t b, uint64_t &sum)
***************************************************************************/
/*-------------------------------------------------
- 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;
@@ -368,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;
@@ -383,6 +385,37 @@ 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
-------------------------------------------------*/