1 /**
2 * Byte Swapping Operations
3 * 
4 * Copyright:
5 * (C) 1999-2011 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 * (C) 2007 Yves Jerschow
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.utils.bswap;
13 
14 import botan.utils.types;
15 import botan.utils.rotate;
16 
17 import botan.constants;
18 static if (BOTAN_HAS_SIMD_SSE2) {
19   import botan.utils.simd.emmintrin;
20 }
21 /**
22 * Swap a 16 bit integer
23 */
24 ushort reverseBytes(ushort val)
25 {
26     return rotateLeft(val, 8);
27 }
28 
29 /**
30 * Swap a 32 bit integer
31 */
32 uint reverseBytes(uint val)
33 {
34     import core.bitop : bswap;
35     return bswap(val);
36 }
37 
38 /**
39 * Swap a 64 bit integer
40 */
41 ulong reverseBytes(ulong val)
42 {
43     static if (is(typeof(bswap64)))
44         return bswap64(val);
45     else {
46         union T { ulong u64; uint[2] u32; }
47         T input, output;
48         input.u64 = val;
49         output.u32[0] = reverseBytes(input.u32[1]);
50         output.u32[1] = reverseBytes(input.u32[0]);
51         return output.u64;
52     }
53 }
54 
55 /**
56 * Swap 4 Ts in an array
57 */
58 void bswap4(T)(ref T[4] x)
59 {
60     x[0] = reverseBytes(x[0]);
61     x[1] = reverseBytes(x[1]);
62     x[2] = reverseBytes(x[2]);
63     x[3] = reverseBytes(x[3]);
64 }
65 
66 static if (BOTAN_HAS_SIMD_SSE2) {
67 
68     /**
69     * Swap 4 uints in an array using SSE2 shuffle instructions
70     */
71     void bswap4(ref uint[4] x)
72     {
73         __m128i T = _mm_loadu_si128(cast(const(__m128i*))(x.ptr));
74 
75         const SHUF = _MM_SHUFFLE(2, 3, 0, 1);
76         T = _mm_shufflehi_epi16!SHUF(T);
77         T = _mm_shufflelo_epi16!SHUF(T);
78 
79         T =  _mm_or_si128(_mm_srli_epi16!8(T), _mm_slli_epi16!8(T));
80 
81         _mm_storeu_si128(cast(__m128i*)(x.ptr), T);
82     }
83 }