Botan  1.10.9
simd_altivec.h
Go to the documentation of this file.
1 /*
2 * Lightweight wrappers around AltiVec for 32-bit operations
3 * (C) 2009 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #ifndef BOTAN_SIMD_ALTIVEC_H__
9 #define BOTAN_SIMD_ALTIVEC_H__
10 
11 #if defined(BOTAN_TARGET_CPU_HAS_ALTIVEC)
12 
13 #include <botan/loadstor.h>
14 #include <botan/cpuid.h>
15 
16 #include <altivec.h>
17 #undef vector
18 #undef bool
19 
20 namespace Botan {
21 
22 class SIMD_Altivec
23  {
24  public:
25  static bool enabled() { return CPUID::has_altivec(); }
26 
27  SIMD_Altivec(const u32bit B[4])
28  {
29  reg = (__vector unsigned int){B[0], B[1], B[2], B[3]};
30  }
31 
32  SIMD_Altivec(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
33  {
34  reg = (__vector unsigned int){B0, B1, B2, B3};
35  }
36 
37  SIMD_Altivec(u32bit B)
38  {
39  reg = (__vector unsigned int){B, B, B, B};
40  }
41 
42  static SIMD_Altivec load_le(const void* in)
43  {
44  const u32bit* in_32 = static_cast<const u32bit*>(in);
45 
46  __vector unsigned int R0 = vec_ld(0, in_32);
47  __vector unsigned int R1 = vec_ld(12, in_32);
48 
49  __vector unsigned char perm = vec_lvsl(0, in_32);
50 
51  perm = vec_xor(perm, vec_splat_u8(3));
52 
53  R0 = vec_perm(R0, R1, perm);
54 
55  return SIMD_Altivec(R0);
56  }
57 
58  static SIMD_Altivec load_be(const void* in)
59  {
60  const u32bit* in_32 = static_cast<const u32bit*>(in);
61 
62  __vector unsigned int R0 = vec_ld(0, in_32);
63  __vector unsigned int R1 = vec_ld(12, in_32);
64 
65  __vector unsigned char perm = vec_lvsl(0, in_32);
66 
67  R0 = vec_perm(R0, R1, perm);
68 
69  return SIMD_Altivec(R0);
70  }
71 
72  void store_le(byte out[]) const
73  {
74  __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
75 
76  perm = vec_xor(perm, vec_splat_u8(3));
77 
78  union {
79  __vector unsigned int V;
80  u32bit R[4];
81  } vec;
82 
83  vec.V = vec_perm(reg, reg, perm);
84 
85  Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
86  }
87 
88  void store_be(byte out[]) const
89  {
90  union {
91  __vector unsigned int V;
92  u32bit R[4];
93  } vec;
94 
95  vec.V = reg;
96 
97  Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
98  }
99 
100  void rotate_left(size_t rot)
101  {
102  __vector unsigned int rot_vec =
103  (__vector unsigned int){rot, rot, rot, rot};
104 
105  reg = vec_rl(reg, rot_vec);
106  }
107 
108  void rotate_right(size_t rot)
109  {
110  rotate_left(32 - rot);
111  }
112 
113  void operator+=(const SIMD_Altivec& other)
114  {
115  reg = vec_add(reg, other.reg);
116  }
117 
118  SIMD_Altivec operator+(const SIMD_Altivec& other) const
119  {
120  return vec_add(reg, other.reg);
121  }
122 
123  void operator-=(const SIMD_Altivec& other)
124  {
125  reg = vec_sub(reg, other.reg);
126  }
127 
128  SIMD_Altivec operator-(const SIMD_Altivec& other) const
129  {
130  return vec_sub(reg, other.reg);
131  }
132 
133  void operator^=(const SIMD_Altivec& other)
134  {
135  reg = vec_xor(reg, other.reg);
136  }
137 
138  SIMD_Altivec operator^(const SIMD_Altivec& other) const
139  {
140  return vec_xor(reg, other.reg);
141  }
142 
143  void operator|=(const SIMD_Altivec& other)
144  {
145  reg = vec_or(reg, other.reg);
146  }
147 
148  SIMD_Altivec operator&(const SIMD_Altivec& other)
149  {
150  return vec_and(reg, other.reg);
151  }
152 
153  void operator&=(const SIMD_Altivec& other)
154  {
155  reg = vec_and(reg, other.reg);
156  }
157 
158  SIMD_Altivec operator<<(size_t shift) const
159  {
160  __vector unsigned int shift_vec =
161  (__vector unsigned int){shift, shift, shift, shift};
162 
163  return vec_sl(reg, shift_vec);
164  }
165 
166  SIMD_Altivec operator>>(size_t shift) const
167  {
168  __vector unsigned int shift_vec =
169  (__vector unsigned int){shift, shift, shift, shift};
170 
171  return vec_sr(reg, shift_vec);
172  }
173 
174  SIMD_Altivec operator~() const
175  {
176  return vec_nor(reg, reg);
177  }
178 
179  SIMD_Altivec andc(const SIMD_Altivec& other)
180  {
181  // AltiVec does arg1 & ~arg2 rather than SSE's ~arg1 & arg2
182  return vec_andc(other.reg, reg);
183  }
184 
185  SIMD_Altivec bswap() const
186  {
187  __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
188 
189  perm = vec_xor(perm, vec_splat_u8(3));
190 
191  return SIMD_Altivec(vec_perm(reg, reg, perm));
192  }
193 
194  static void transpose(SIMD_Altivec& B0, SIMD_Altivec& B1,
195  SIMD_Altivec& B2, SIMD_Altivec& B3)
196  {
197  __vector unsigned int T0 = vec_mergeh(B0.reg, B2.reg);
198  __vector unsigned int T1 = vec_mergel(B0.reg, B2.reg);
199  __vector unsigned int T2 = vec_mergeh(B1.reg, B3.reg);
200  __vector unsigned int T3 = vec_mergel(B1.reg, B3.reg);
201 
202  B0.reg = vec_mergeh(T0, T2);
203  B1.reg = vec_mergel(T0, T2);
204  B2.reg = vec_mergeh(T1, T3);
205  B3.reg = vec_mergel(T1, T3);
206  }
207 
208  private:
209  SIMD_Altivec(__vector unsigned int input) { reg = input; }
210 
211  __vector unsigned int reg;
212  };
213 
214 }
215 
216 #endif
217 
218 #endif
T load_be(const byte in[], size_t off)
Definition: loadstor.h:100
T load_le(const byte in[], size_t off)
Definition: loadstor.h:116
void store_le(u16bit in, byte out[2])
Definition: loadstor.h:427
T rotate_left(T input, size_t rot)
Definition: rotate.h:21
int operator>>(int fd, Pipe &pipe)
Definition: fd_unix.cpp:39
static bool has_altivec()
Definition: cpuid.h:94
#define R0
Definition: asm_x86_64.h:51
OctetString operator^(const OctetString &k1, const OctetString &k2)
Definition: symkey.cpp:125
unsigned char byte
Definition: types.h:22
int operator<<(int fd, Pipe &pipe)
Definition: fd_unix.cpp:17
OctetString operator+(const OctetString &k1, const OctetString &k2)
Definition: symkey.cpp:114
T rotate_right(T input, size_t rot)
Definition: rotate.h:34
MemoryRegion< T > & operator+=(MemoryRegion< T > &out, const MemoryRegion< T > &in)
Definition: secmem.h:373
#define R1
Definition: asm_x86_64.h:52
void store_be(u16bit in, byte out[2])
Definition: loadstor.h:412
BigInt operator-(const BigInt &x, const BigInt &y)
Definition: big_ops3.cpp:48
unsigned int u32bit
Definition: types.h:32