Home | History | Annotate | Download | only in cpu
      1 #ifndef _CPU_MATH_H_
      2 #define _CPU_MATH_H_
      3 
      4 #include <stdint.h>
      5 
      6 uint32_t cpuMathUint44Div1000ToUint32_slow_path(uint64_t val);
      7 
      8 static inline uint32_t cpuMathUint44Div1000ToUint32(uint64_t val)
      9 {
     10     if (val >> 32)
     11         return cpuMathUint44Div1000ToUint32_slow_path(val);
     12     else
     13         return (uint32_t)val / 1000;
     14 }
     15 
     16 uint64_t cpuMathU64DivByU16(uint64_t val, uint32_t divBy /* 16 bits max*/);
     17 
     18 //DO NOT USE ON NON_COMPILE-TIME-CONSTANT VALUES OF u16, use cpuMathU64DivByU16()
     19 
     20 #define U64_DIV_BY_CONST_U16(u64, u16)                        \
     21     ({                                                        \
     22         const uint16_t divBy = u16;                           \
     23         const uint64_t _num = u64;                            \
     24         const uint32_t numHi = _num >> 32, numLo = _num;      \
     25         uint32_t t1, t2, t3, t4, t5;                          \
     26                                                               \
     27         t1 = numHi / divBy;                                   \
     28         t2 = numHi % divBy;                                   \
     29         t2 <<= 16;                                            \
     30         t2 += numLo >> 16;                                    \
     31         t3 = t2 / divBy;                                      \
     32         t4 = t2 % divBy;                                      \
     33         t4 <<= 16;                                            \
     34         t4 += numLo & 0xFFFF;                                 \
     35         t5 = t4 / divBy;                                      \
     36                                                               \
     37         (((uint64_t)t1) << 32) + (((uint64_t)t3) << 16) + t5; \
     38     })
     39 
     40 //correctly handles 0, 1, powers of 2, and all else to calculate "(1 << 64) / val"
     41 //do not even think of using this on non-compile-time-constant values!
     42 #define U64_RECIPROCAL_CALCULATE(val)  ((val) & ((val) - 1)) ? (0xffffffffffffffffull / (val)) : (((val) <= 1) ? 0xffffffffffffffffull : (0x8000000000000000ull / ((val) >> 1)))
     43 
     44 uint64_t cpuMathRecipAssistedUdiv64by64(uint64_t num, uint64_t denom, uint64_t denomRecip);
     45 uint64_t cpuMathRecipAssistedUdiv64by32(uint64_t num, uint32_t denom, uint64_t denomRecip);
     46 
     47 #define U64_DIV_BY_U64_CONSTANT(val, constantVal)  cpuMathRecipAssistedUdiv64by64((val), (constantVal), U64_RECIPROCAL_CALCULATE(constantVal))
     48 #define I64_DIV_BY_I64_CONSTANT(val, constantVal)                                                  \
     49     ({                                                                                             \
     50         char neg = ((uint32_t)((val) >> 32) ^ (uint32_t)(((uint64_t)(constantVal)) >> 32)) >> 31;  \
     51         uint64_t valP = (val < 0) ? -val : val;                                                    \
     52         const uint64_t conP = (constantVal < 0) ? -constantVal : constantVal;                      \
     53         uint64_t ret = cpuMathRecipAssistedUdiv64by64(valP, conP, U64_RECIPROCAL_CALCULATE(conP)); \
     54         if (neg)                                                                                   \
     55             ret =-ret;                                                                             \
     56         ret;                                                                                       \
     57     })
     58 
     59 
     60 #endif
     61 
     62