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 }