1 // [AsmJit]
2 // Complete JIT Assembler for C++ Language.
3 //
4 // [License]
5 // Zlib - See COPYING file in this package.
6 
7 // [Guard]
8 #ifndef _ASMJIT_CORE_INTUTIL_H
9 #define _ASMJIT_CORE_INTUTIL_H
10 
11 // [Dependencies - AsmJit]
12 #include "../core/assert.h"
13 
14 // [Api-Begin]
15 #include "../core/apibegin.h"
16 
17 namespace AsmJit {
18 
19 //! @addtogroup AsmJit_Core
20 //! @{
21 
22 // ============================================================================
23 // [AsmJit::I32FPUnion]
24 // ============================================================================
25 
26 //! @internal
27 //!
28 //! @brief used to cast from float to 32-bit integer and vica versa.
29 union I32FPUnion
30 {
31   //! @brief 32-bit signed integer value.
32   int32_t i;
33   //! @brief 32-bit SP-FP value.
34   float f;
35 };
36 
37 // ============================================================================
38 // [AsmJit::I64FPUnion]
39 // ============================================================================
40 
41 //! @internal
42 //!
43 //! @brief used to cast from double to 64-bit integer and vica versa.
44 union I64FPUnion
45 {
46   //! @brief 64-bit signed integer value.
47   int64_t i;
48   //! @brief 64-bit DP-FP value.
49   double f;
50 };
51 
52 // ============================================================================
53 // [AsmJit::IntUtil]
54 // ============================================================================
55 
56 namespace IntUtil
57 {
58   // --------------------------------------------------------------------------
59   // [Min/Max]
60   // --------------------------------------------------------------------------
61 
62   // NOTE: Because some environments declare min() and max() as macros, we
63   // decided to use different name so we never collide.
64 
65   template<typename T>
_min(const T & a,const T & b)66   static inline T _min(const T& a, const T& b) { return a < b ? a : b; }
67   template<typename T>
_max(const T & a,const T & b)68   static inline T _max(const T& a, const T& b) { return a > b ? a : b; }
69 
70   // --------------------------------------------------------------------------
71   // [Limits]
72   // --------------------------------------------------------------------------
73 
74   template<typename T>
maxValue()75   static inline T maxValue() { return ~T(0); }
76 
77   // --------------------------------------------------------------------------
78   // [IsInt / IsUInt]
79   // --------------------------------------------------------------------------
80 
81   //! @brief Returns @c true if a given integer @a x is signed 8-bit integer
isInt8(intptr_t x)82   static inline bool isInt8(intptr_t x) { return x >= -128 && x <= 127; }
83   //! @brief Returns @c true if a given integer @a x is unsigned 8-bit integer
isUInt8(intptr_t x)84   static inline bool isUInt8(intptr_t x) { return x >= 0 && x <= 255; }
85 
86   //! @brief Returns @c true if a given integer @a x is signed 16-bit integer
isInt16(intptr_t x)87   static inline bool isInt16(intptr_t x) { return x >= -32768 && x <= 32767; }
88   //! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer
isUInt16(intptr_t x)89   static inline bool isUInt16(intptr_t x) { return x >= 0 && x <= 65535; }
90 
91   //! @brief Returns @c true if a given integer @a x is signed 16-bit integer
isInt32(intptr_t x)92   static inline bool isInt32(intptr_t x)
93   {
94 #if defined(ASMJIT_X86)
95     return true;
96 #else
97     return x >= ASMJIT_INT64_C(-2147483648) && x <= ASMJIT_INT64_C(2147483647);
98 #endif
99   }
100   //! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer
isUInt32(intptr_t x)101   static inline bool isUInt32(intptr_t x)
102   {
103 #if defined(ASMJIT_X86)
104     return x >= 0;
105 #else
106     return x >= 0 && x <= ASMJIT_INT64_C(4294967295);
107 #endif
108   }
109 
110   // --------------------------------------------------------------------------
111   // [Masking]
112   // --------------------------------------------------------------------------
113 
maskFromIndex(uint32_t x)114   static inline uint32_t maskFromIndex(uint32_t x)
115   {
116     ASMJIT_ASSERT(x < 32);
117     return (1U << x);
118   }
119 
maskUpToIndex(uint32_t x)120   static inline uint32_t maskUpToIndex(uint32_t x)
121   {
122     if (x >= 32)
123       return 0xFFFFFFFF;
124     else
125       return (1U << x) - 1;
126   }
127 
128   // --------------------------------------------------------------------------
129   // [Bits]
130   // --------------------------------------------------------------------------
131 
132   // From http://graphics.stanford.edu/~seander/bithacks.html .
bitCount(uint32_t x)133   static inline uint32_t bitCount(uint32_t x)
134   {
135     x = x - ((x >> 1) & 0x55555555U);
136     x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
137     return (((x + (x >> 4)) & 0x0F0F0F0FU) * 0x01010101U) >> 24;
138   }
139 
findFirstBit(uint32_t mask)140   static inline uint32_t findFirstBit(uint32_t mask)
141   {
142     for (uint32_t i = 0; i < sizeof(uint32_t) * 8; i++, mask >>= 1)
143     {
144       if (mask & 0x1)
145         return i;
146     }
147 
148     // kInvalidValue.
149     return 0xFFFFFFFF;
150   }
151 
152   // --------------------------------------------------------------------------
153   // [Alignment]
154   // --------------------------------------------------------------------------
155 
156   template<typename T>
isAligned(T base,T alignment)157   static inline bool isAligned(T base, T alignment)
158   {
159     return (base % alignment) == 0;
160   }
161 
162   //! @brief Align @a base to @a alignment.
163   template<typename T>
align(T base,T alignment)164   static inline T align(T base, T alignment)
165   {
166     return (base + (alignment - 1)) & ~(alignment - 1);
167   }
168 
169   //! @brief Get delta required to align @a base to @a alignment.
170   template<typename T>
delta(T base,T alignment)171   static inline T delta(T base, T alignment)
172   {
173     return align(base, alignment) - base;
174   }
175 
176   // --------------------------------------------------------------------------
177   // [Round]
178   // --------------------------------------------------------------------------
179 
180   template<typename T>
roundUp(T base,T alignment)181   static inline T roundUp(T base, T alignment)
182   {
183     T over = base % alignment;
184     return base + (over > 0 ? alignment - over : 0);
185   }
186 
187   template<typename T>
roundUpToPowerOf2(T base)188   static inline T roundUpToPowerOf2(T base)
189   {
190     // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
191     // figure 3-3, page 48, where the function is called clp2.
192     base -= 1;
193 
194     // I'm trying to make this portable and MSVC strikes me the warning C4293:
195     //   "Shift count negative or too big, undefined behavior"
196     // Fixing...
197 #if defined(_MSC_VER)
198 # pragma warning(push)
199 # pragma warning(disable: 4293)
200 #endif // _MSC_VER
201 
202     base = base | (base >> 1);
203     base = base | (base >> 2);
204     base = base | (base >> 4);
205 
206     if (sizeof(T) >= 2) base = base | (base >>  8);
207     if (sizeof(T) >= 4) base = base | (base >> 16);
208     if (sizeof(T) >= 8) base = base | (base >> 16 >> 16);
209 
210 #if defined(_MSC_VER)
211 # pragma warning(pop)
212 #endif // _MSC_VER
213 
214     return base + 1;
215   }
216 
217   // --------------------------------------------------------------------------
218   // [Cast]
219   // --------------------------------------------------------------------------
220 
221   //! @brief Binary cast from 32-bit integer to SP-FP value (@c float).
int32AsFloat(int32_t i)222   static inline float int32AsFloat(int32_t i)
223   {
224     I32FPUnion u;
225     u.i = i;
226     return u.f;
227   }
228 
229   //! @brief Binary cast SP-FP value (@c float) to 32-bit integer.
floatAsInt32(float f)230   static inline int32_t floatAsInt32(float f)
231   {
232     I32FPUnion u;
233     u.f = f;
234     return u.i;
235   }
236 
237   //! @brief Binary cast from 64-bit integer to DP-FP value (@c double).
int64AsDouble(int64_t i)238   static inline double int64AsDouble(int64_t i)
239   {
240     I64FPUnion u;
241     u.i = i;
242     return u.f;
243   }
244 
245   //! @brief Binary cast from DP-FP value (@c double) to 64-bit integer.
doubleAsInt64(double f)246   static inline int64_t doubleAsInt64(double f)
247   {
248     I64FPUnion u;
249     u.f = f;
250     return u.i;
251   }
252 };
253 
254 //! @}
255 
256 } // AsmJit namespace
257 
258 // [Api-End]
259 #include "../core/apiend.h"
260 
261 // [Guard]
262 #endif // _ASMJIT_CORE_INTUTIL_H
263