Botan 1.10.17
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
20namespace Botan {
21
22class 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
#define R0
Definition asm_x86_64.h:51
#define R1
Definition asm_x86_64.h:52
int operator>>(int fd, Pipe &pipe)
Definition fd_unix.cpp:39
OctetString operator+(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:114
T load_be(const byte in[], size_t off)
Definition loadstor.h:100
T rotate_right(T input, size_t rot)
Definition rotate.h:34
T rotate_left(T input, size_t rot)
Definition rotate.h:21
T load_le(const byte in[], size_t off)
Definition loadstor.h:116
unsigned int u32bit
Definition types.h:32
BigInt operator-(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:48
int operator<<(int fd, Pipe &pipe)
Definition fd_unix.cpp:17
OctetString operator^(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:125
void store_be(u16bit in, byte out[2])
Definition loadstor.h:412
MemoryRegion< T > & operator+=(MemoryRegion< T > &out, const MemoryRegion< T > &in)
Definition secmem.h:386
void store_le(u16bit in, byte out[2])
Definition loadstor.h:427