Botan  1.11.15
src/lib/utils/simd/simd_altivec/simd_altivec.h
Go to the documentation of this file.
00001 /*
00002 * Lightweight wrappers around AltiVec for 32-bit operations
00003 * (C) 2009 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_SIMD_ALTIVEC_H__
00009 #define BOTAN_SIMD_ALTIVEC_H__
00010 
00011 #if defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
00012 
00013 #include <botan/loadstor.h>
00014 #include <botan/cpuid.h>
00015 
00016 #include <altivec.h>
00017 #undef vector
00018 #undef bool
00019 
00020 namespace Botan {
00021 
00022 class SIMD_Altivec
00023    {
00024    public:
00025       static bool enabled() { return CPUID::has_altivec(); }
00026 
00027       SIMD_Altivec(const u32bit B[4])
00028          {
00029          m_reg = (__vector unsigned int){B[0], B[1], B[2], B[3]};
00030          }
00031 
00032       SIMD_Altivec(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
00033          {
00034          m_reg = (__vector unsigned int){B0, B1, B2, B3};
00035          }
00036 
00037       SIMD_Altivec(u32bit B)
00038          {
00039          m_reg = (__vector unsigned int){B, B, B, B};
00040          }
00041 
00042       static SIMD_Altivec load_le(const void* in)
00043          {
00044          const u32bit* in_32 = static_cast<const u32bit*>(in);
00045 
00046          __vector unsigned int R0 = vec_ld(0, in_32);
00047          __vector unsigned int R1 = vec_ld(12, in_32);
00048 
00049          __vector unsigned char perm = vec_lvsl(0, in_32);
00050 
00051          perm = vec_xor(perm, vec_splat_u8(3));
00052 
00053          R0 = vec_perm(R0, R1, perm);
00054 
00055          return SIMD_Altivec(R0);
00056          }
00057 
00058       static SIMD_Altivec load_be(const void* in)
00059          {
00060          const u32bit* in_32 = static_cast<const u32bit*>(in);
00061 
00062          __vector unsigned int R0 = vec_ld(0, in_32);
00063          __vector unsigned int R1 = vec_ld(12, in_32);
00064 
00065          __vector unsigned char perm = vec_lvsl(0, in_32);
00066 
00067          R0 = vec_perm(R0, R1, perm);
00068 
00069          return SIMD_Altivec(R0);
00070          }
00071 
00072       void store_le(byte out[]) const
00073          {
00074          __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
00075 
00076          perm = vec_xor(perm, vec_splat_u8(3));
00077 
00078          union {
00079             __vector unsigned int V;
00080             u32bit R[4];
00081             } vec;
00082 
00083          vec.V = vec_perm(m_reg, m_reg, perm);
00084 
00085          Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
00086          }
00087 
00088       void store_be(byte out[]) const
00089          {
00090          union {
00091             __vector unsigned int V;
00092             u32bit R[4];
00093             } vec;
00094 
00095          vec.V = m_reg;
00096 
00097          Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
00098          }
00099 
00100       void rotate_left(size_t rot)
00101          {
00102          const unsigned int r = static_cast<unsigned int>(rot);
00103          m_reg = vec_rl(m_reg, (__vector unsigned int){r, r, r, r});
00104          }
00105 
00106       void rotate_right(size_t rot)
00107          {
00108          rotate_left(32 - rot);
00109          }
00110 
00111       void operator+=(const SIMD_Altivec& other)
00112          {
00113          m_reg = vec_add(m_reg, other.m_reg);
00114          }
00115 
00116       SIMD_Altivec operator+(const SIMD_Altivec& other) const
00117          {
00118          return vec_add(m_reg, other.m_reg);
00119          }
00120 
00121       void operator-=(const SIMD_Altivec& other)
00122          {
00123          m_reg = vec_sub(m_reg, other.m_reg);
00124          }
00125 
00126       SIMD_Altivec operator-(const SIMD_Altivec& other) const
00127          {
00128          return vec_sub(m_reg, other.m_reg);
00129          }
00130 
00131       void operator^=(const SIMD_Altivec& other)
00132          {
00133          m_reg = vec_xor(m_reg, other.m_reg);
00134          }
00135 
00136       SIMD_Altivec operator^(const SIMD_Altivec& other) const
00137          {
00138          return vec_xor(m_reg, other.m_reg);
00139          }
00140 
00141       void operator|=(const SIMD_Altivec& other)
00142          {
00143          m_reg = vec_or(m_reg, other.m_reg);
00144          }
00145 
00146       SIMD_Altivec operator&(const SIMD_Altivec& other)
00147          {
00148          return vec_and(m_reg, other.m_reg);
00149          }
00150 
00151       void operator&=(const SIMD_Altivec& other)
00152          {
00153          m_reg = vec_and(m_reg, other.m_reg);
00154          }
00155 
00156       SIMD_Altivec operator<<(size_t shift) const
00157          {
00158          const unsigned int s = static_cast<unsigned int>(shift);
00159          return vec_sl(m_reg, (__vector unsigned int){s, s, s, s});
00160          }
00161 
00162       SIMD_Altivec operator>>(size_t shift) const
00163          {
00164          const unsigned int s = static_cast<unsigned int>(shift);
00165          return vec_sr(m_reg, (__vector unsigned int){s, s, s, s});
00166          }
00167 
00168       SIMD_Altivec operator~() const
00169          {
00170          return vec_nor(m_reg, m_reg);
00171          }
00172 
00173       SIMD_Altivec andc(const SIMD_Altivec& other)
00174          {
00175          /*
00176          AltiVec does arg1 & ~arg2 rather than SSE's ~arg1 & arg2
00177          so swap the arguments
00178          */
00179          return vec_andc(other.m_reg, m_reg);
00180          }
00181 
00182       SIMD_Altivec bswap() const
00183          {
00184          __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
00185 
00186          perm = vec_xor(perm, vec_splat_u8(3));
00187 
00188          return SIMD_Altivec(vec_perm(m_reg, m_reg, perm));
00189          }
00190 
00191       static void transpose(SIMD_Altivec& B0, SIMD_Altivec& B1,
00192                             SIMD_Altivec& B2, SIMD_Altivec& B3)
00193          {
00194          __vector unsigned int T0 = vec_mergeh(B0.m_reg, B2.m_reg);
00195          __vector unsigned int T1 = vec_mergel(B0.m_reg, B2.m_reg);
00196          __vector unsigned int T2 = vec_mergeh(B1.m_reg, B3.m_reg);
00197          __vector unsigned int T3 = vec_mergel(B1.m_reg, B3.m_reg);
00198 
00199          B0.m_reg = vec_mergeh(T0, T2);
00200          B1.m_reg = vec_mergel(T0, T2);
00201          B2.m_reg = vec_mergeh(T1, T3);
00202          B3.m_reg = vec_mergel(T1, T3);
00203          }
00204 
00205    private:
00206       SIMD_Altivec(__vector unsigned int input) { m_reg = input; }
00207 
00208       __vector unsigned int m_reg;
00209    };
00210 
00211 }
00212 
00213 #endif
00214 
00215 #endif