/src/Botan-3.4.0/build/include/internal/botan/internal/mul128.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * 64x64->128 bit multiply operation |
3 | | * (C) 2013,2015 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #ifndef BOTAN_UTIL_MUL128_H_ |
9 | | #define BOTAN_UTIL_MUL128_H_ |
10 | | |
11 | | #include <botan/types.h> |
12 | | #include <type_traits> |
13 | | |
14 | | #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT) |
15 | | #include <intrin.h> |
16 | | #endif |
17 | | |
18 | | namespace Botan { |
19 | | |
20 | | /** |
21 | | * Perform a 64x64->128 bit multiplication |
22 | | */ |
23 | 0 | constexpr inline void mul64x64_128(uint64_t a, uint64_t b, uint64_t* lo, uint64_t* hi) { |
24 | 0 | if(!std::is_constant_evaluated()) { |
25 | 0 | #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) && defined(BOTAN_TARGET_ARCH_IS_X86_64) |
26 | 0 | *lo = _umul128(a, b, hi); |
27 | 0 | return; |
28 | 0 |
|
29 | 0 | #elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) && defined(BOTAN_TARGET_ARCH_IS_ARM64) |
30 | 0 | *lo = a * b; |
31 | 0 | *hi = __umulh(a, b); |
32 | 0 | return; |
33 | 0 | #endif |
34 | 0 | } |
35 | 0 |
|
36 | 0 | #if defined(BOTAN_TARGET_HAS_NATIVE_UINT128) |
37 | 0 | const uint128_t r = static_cast<uint128_t>(a) * b; |
38 | 0 | *hi = (r >> 64) & 0xFFFFFFFFFFFFFFFF; |
39 | 0 | *lo = (r)&0xFFFFFFFFFFFFFFFF; |
40 | 0 | #else |
41 | 0 |
|
42 | 0 | /* |
43 | 0 | * Do a 64x64->128 multiply using four 32x32->64 multiplies plus |
44 | 0 | * some adds and shifts. |
45 | 0 | */ |
46 | 0 | const size_t HWORD_BITS = 32; |
47 | 0 | const uint32_t HWORD_MASK = 0xFFFFFFFF; |
48 | 0 |
|
49 | 0 | const uint32_t a_hi = (a >> HWORD_BITS); |
50 | 0 | const uint32_t a_lo = (a & HWORD_MASK); |
51 | 0 | const uint32_t b_hi = (b >> HWORD_BITS); |
52 | 0 | const uint32_t b_lo = (b & HWORD_MASK); |
53 | 0 |
|
54 | 0 | const uint64_t x0 = static_cast<uint64_t>(a_hi) * b_hi; |
55 | 0 | const uint64_t x1 = static_cast<uint64_t>(a_lo) * b_hi; |
56 | 0 | const uint64_t x2 = static_cast<uint64_t>(a_hi) * b_lo; |
57 | 0 | const uint64_t x3 = static_cast<uint64_t>(a_lo) * b_lo; |
58 | 0 |
|
59 | 0 | // this cannot overflow as (2^32-1)^2 + 2^32-1 + 2^32-1 = 2^64-1 |
60 | 0 | const uint64_t middle = x2 + (x3 >> HWORD_BITS) + (x1 & HWORD_MASK); |
61 | 0 |
|
62 | 0 | // likewise these cannot overflow |
63 | 0 | *hi = x0 + (middle >> HWORD_BITS) + (x1 >> HWORD_BITS); |
64 | 0 | *lo = (middle << HWORD_BITS) + (x3 & HWORD_MASK); |
65 | 0 | #endif |
66 | 0 | } |
67 | | |
68 | | } // namespace Botan |
69 | | |
70 | | #endif |