Home | History | Annotate | Download | only in cortexm4
      1 #include <cpu/cpuMath.h>
      2 
      3 uint32_t cpuMathUint44Div1000ToUint32_slow_path(uint64_t val)
      4 {
      5     uint64_t mult = 0x4189374BCULL;
      6     uint32_t multLo = mult;
      7     uint32_t multHi = mult >> 32;
      8     uint64_t ret;
      9 
     10     ret = val * multLo;
     11     ret >>= 32;
     12     ret += val * multHi;
     13 
     14     return ret >> 12;
     15 }
     16 
     17 uint64_t cpuMathU64DivByU16(uint64_t val, uint32_t divBy_ /* 16 bits max*/)
     18 {
     19     //this is OK here, but not elsewhere
     20     return U64_DIV_BY_CONST_U16(val, divBy_);
     21 }
     22 
     23 static uint64_t __attribute__((naked)) cpuMathUint64TimesUint64Lsr64(uint64_t a, uint64_t b)
     24 {
     25     asm volatile(
     26         "push  {r4 - r7}        \n"
     27         "umull r12, r4, r0, r2  \n"
     28         "umull r5, r6, r0, r3   \n"
     29         "umull r7, r12, r1, r2  \n"
     30         "movs  r2, #0           \n"
     31         "adds  r5, r4           \n"
     32         "adcs  r6, r2           \n"
     33         "adds  r5, r7           \n"
     34         "adc   r0, r6, r12      \n"
     35         "umlal r0, r2, r1, r3   \n"
     36         "movs  r1, r2           \n"
     37         "pop   {r4 - r7}        \n"
     38         "bx    lr               \n"
     39     );
     40 
     41     //we never get here, it is only here to please GCC
     42     return 0;
     43 }
     44 
     45 //this will be specialized for both cases (compiler can use denom being 32-bit long easily)
     46 #define cpuMathRecipAssistedUdiv64_common                  \
     47     uint64_t try, ret;                                     \
     48                                                            \
     49     if (denom <= 1)                                        \
     50         return num;                                        \
     51                                                            \
     52     ret = cpuMathUint64TimesUint64Lsr64(num, denomRecip);  \
     53     try = (ret + 1) * denom;                               \
     54     if (try <= num && try >= ret * denom)                  \
     55         ret++;                                             \
     56                                                            \
     57     return ret;
     58 
     59 uint64_t cpuMathRecipAssistedUdiv64by64(uint64_t num, uint64_t denom, uint64_t denomRecip)
     60 {
     61     cpuMathRecipAssistedUdiv64_common
     62 }
     63 
     64 uint64_t cpuMathRecipAssistedUdiv64by32(uint64_t num, uint32_t denom, uint64_t denomRecip)
     65 {
     66     cpuMathRecipAssistedUdiv64_common
     67 }
     68