mem: Fix memory allocation bug in deferred snoop handling
[gem5.git] / src / base / bitfield.hh
index 879780d5600c3cae37ecdf6874a41c4389194c83..5a98b13c75e219383499e5ce4de467a1fe7389ad 100644 (file)
@@ -32,7 +32,7 @@
 #ifndef __BASE_BITFIELD_HH__
 #define __BASE_BITFIELD_HH__
 
-#include <inttypes.h>
+#include "base/types.hh"
 
 /**
  * Generate a 64-bit mask of 'nbits' 1s, right justified.
@@ -44,6 +44,7 @@ mask(int nbits)
 }
 
 
+
 /**
  * Extract the bitfield from position 'first' to 'last' (inclusive)
  * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
@@ -57,16 +58,157 @@ bits(T val, int first, int last)
     return (val >> last) & mask(nbits);
 }
 
+/**
+ * Extract the bit from this position from 'val' and right justify it.
+ */
+template <class T>
+inline
+T
+bits(T val, int bit)
+{
+    return bits(val, bit, bit);
+}
+
+/**
+ * Mask off the given bits in place like bits() but without shifting.
+ * msb = 63, lsb = 0
+ */
+template <class T>
+inline
+T
+mbits(T val, int first, int last)
+{
+    return val & (mask(first+1) & ~mask(last));
+}
+
+inline uint64_t
+mask(int first, int last)
+{
+    return mbits((uint64_t)-1LL, first, last);
+}
+
 /**
  * Sign-extend an N-bit value to 64 bits.
  */
 template <int N>
 inline
-int64_t
+uint64_t
 sext(uint64_t val)
 {
     int sign_bit = bits(val, N-1, N-1);
     return sign_bit ? (val | ~mask(N)) : val;
 }
 
+/**
+ * Return val with bits first to last set to bit_val
+ */
+template <class T, class B>
+inline
+T
+insertBits(T val, int first, int last, B bit_val)
+{
+    T t_bit_val = bit_val;
+    T bmask = mask(first - last + 1) << last;
+    return ((t_bit_val << last) & bmask) | (val & ~bmask);
+}
+
+/**
+ * Overloaded for access to only one bit in value
+ */
+template <class T, class B>
+inline
+T
+insertBits(T val, int bit, B bit_val)
+{
+    return insertBits(val, bit, bit, bit_val);
+}
+
+/**
+ * A convenience function to replace bits first to last of val with bit_val
+ * in place.
+ */
+template <class T, class B>
+inline
+void
+replaceBits(T& val, int first, int last, B bit_val)
+{
+    val = insertBits(val, first, last, bit_val);
+}
+
+/** Overloaded function to allow to access only 1 bit*/
+template <class T, class B>
+inline
+void
+replaceBits(T& val, int bit, B bit_val)
+{
+    val = insertBits(val, bit, bit, bit_val);
+}
+/**
+ * Returns the bit position of the MSB that is set in the input
+ */
+inline
+int
+findMsbSet(uint64_t val) {
+    int msb = 0;
+    if (!val)
+        return 0;
+    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
+    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
+    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
+    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
+    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
+    if (bits(val, 1,1))   { msb += 1; }
+    return msb;
+}
+
+/**
+ * Returns the bit position of the LSB that is set in the input
+ */
+inline int
+findLsbSet(uint64_t val) {
+    int lsb = 0;
+    if (!val)
+        return sizeof(val) * 8;
+    if (!bits(val, 31,0)) { lsb += 32; val >>= 32; }
+    if (!bits(val, 15,0)) { lsb += 16; val >>= 16; }
+    if (!bits(val, 7,0))  { lsb += 8;  val >>= 8;  }
+    if (!bits(val, 3,0))  { lsb += 4;  val >>= 4;  }
+    if (!bits(val, 1,0))  { lsb += 2;  val >>= 2;  }
+    if (!bits(val, 0,0))  { lsb += 1; }
+    return lsb;
+}
+
+/**
+ * Checks if a number is a power of two, or zero.
+ */
+template <class T>
+inline bool
+isPow2(T v) {
+   return (v & (v - 1)) == (T)0;
+}
+
+/**
+ * Returns the number of set ones in the provided value.
+ * PD algorithm from
+ * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ */
+inline int
+popCount(uint64_t val) {
+#ifndef __has_builtin
+    #define __has_builtin(foo) 0
+#endif
+#if defined(__GNUC__) || (defined(__clang__) && __has_builtin(__builtin_popcountl))
+    return __builtin_popcountl(val);
+#else
+    const uint64_t m1 = 0x5555555555555555;  // ..010101b
+    const uint64_t m2 = 0x3333333333333333;  // ..110011b
+    const uint64_t m4 = 0x0f0f0f0f0f0f0f0f;  // ..001111b
+    const uint64_t sum = 0x0101010101010101;
+
+    val -= (val >> 1) & m1;               // 2 bits count -> 2 bits
+    val = (val & m2) + ((val >> 2) & m2); // 4 bits count -> 4 bits
+    val = (val + (val >> 4)) & m4;        // 8 bits count -> 8 bits
+    return (val * sum) >> 56;             // horizontal sum
+#endif // defined(__GNUC__) || (defined(__clang__) && __has_builtin(__builtin_popcountl))
+}
 #endif // __BASE_BITFIELD_HH__