1 #include <cpu/inc/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