Merge f_arithmetic.c into f_generic.c
[openssl.git] / crypto / ec / curve448 / arch_x86_64 / f_impl.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright 2014 Cryptography Research, Inc.
4  *
5  * Licensed under the OpenSSL license (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  *
10  * Originally written by Mike Hamburg
11  */
12
13 #include "f_field.h"
14
15 void gf_mul(gf_s * __restrict__ cs, const gf as, const gf bs)
16 {
17     const uint64_t *a = as->limb, *b = bs->limb;
18     uint64_t *c = cs->limb;
19     __uint128_t accum0 = 0, accum1 = 0, accum2;
20     uint64_t mask = (1ull << 56) - 1;
21     uint64_t aa[4] VECTOR_ALIGNED, bb[4] VECTOR_ALIGNED, bbb[4] VECTOR_ALIGNED;
22
23     /* For some reason clang doesn't vectorize this without prompting? */
24     unsigned int i;
25     for (i = 0; i < sizeof(aa) / sizeof(uint64xn_t); i++) {
26         ((uint64xn_t *) aa)[i] =
27             ((const uint64xn_t *)a)[i] + ((const uint64xn_t *)(&a[4]))[i];
28         ((uint64xn_t *) bb)[i] =
29             ((const uint64xn_t *)b)[i] + ((const uint64xn_t *)(&b[4]))[i];
30         ((uint64xn_t *) bbb)[i] =
31             ((const uint64xn_t *)bb)[i] + ((const uint64xn_t *)(&b[4]))[i];
32     }
33     /*
34      * for (int i=0; i<4; i++) { aa[i] = a[i] + a[i+4]; bb[i] = b[i] + b[i+4];
35      * }
36      */
37
38     accum2 = widemul(&a[0], &b[3]);
39     accum0 = widemul(&aa[0], &bb[3]);
40     accum1 = widemul(&a[4], &b[7]);
41
42     mac(&accum2, &a[1], &b[2]);
43     mac(&accum0, &aa[1], &bb[2]);
44     mac(&accum1, &a[5], &b[6]);
45
46     mac(&accum2, &a[2], &b[1]);
47     mac(&accum0, &aa[2], &bb[1]);
48     mac(&accum1, &a[6], &b[5]);
49
50     mac(&accum2, &a[3], &b[0]);
51     mac(&accum0, &aa[3], &bb[0]);
52     mac(&accum1, &a[7], &b[4]);
53
54     accum0 -= accum2;
55     accum1 += accum2;
56
57     c[3] = ((uint64_t)(accum1)) & mask;
58     c[7] = ((uint64_t)(accum0)) & mask;
59
60     accum0 >>= 56;
61     accum1 >>= 56;
62
63     mac(&accum0, &aa[1], &bb[3]);
64     mac(&accum1, &a[5], &b[7]);
65     mac(&accum0, &aa[2], &bb[2]);
66     mac(&accum1, &a[6], &b[6]);
67     mac(&accum0, &aa[3], &bb[1]);
68     accum1 += accum0;
69
70     accum2 = widemul(&a[0], &b[0]);
71     accum1 -= accum2;
72     accum0 += accum2;
73
74     msb(&accum0, &a[1], &b[3]);
75     msb(&accum0, &a[2], &b[2]);
76     mac(&accum1, &a[7], &b[5]);
77     msb(&accum0, &a[3], &b[1]);
78     mac(&accum1, &aa[0], &bb[0]);
79     mac(&accum0, &a[4], &b[4]);
80
81     c[0] = ((uint64_t)(accum0)) & mask;
82     c[4] = ((uint64_t)(accum1)) & mask;
83
84     accum0 >>= 56;
85     accum1 >>= 56;
86
87     accum2 = widemul(&a[2], &b[7]);
88     mac(&accum0, &a[6], &bb[3]);
89     mac(&accum1, &aa[2], &bbb[3]);
90
91     mac(&accum2, &a[3], &b[6]);
92     mac(&accum0, &a[7], &bb[2]);
93     mac(&accum1, &aa[3], &bbb[2]);
94
95     mac(&accum2, &a[0], &b[1]);
96     mac(&accum1, &aa[0], &bb[1]);
97     mac(&accum0, &a[4], &b[5]);
98
99     mac(&accum2, &a[1], &b[0]);
100     mac(&accum1, &aa[1], &bb[0]);
101     mac(&accum0, &a[5], &b[4]);
102
103     accum1 -= accum2;
104     accum0 += accum2;
105
106     c[1] = ((uint64_t)(accum0)) & mask;
107     c[5] = ((uint64_t)(accum1)) & mask;
108
109     accum0 >>= 56;
110     accum1 >>= 56;
111
112     accum2 = widemul(&a[3], &b[7]);
113     mac(&accum0, &a[7], &bb[3]);
114     mac(&accum1, &aa[3], &bbb[3]);
115
116     mac(&accum2, &a[0], &b[2]);
117     mac(&accum1, &aa[0], &bb[2]);
118     mac(&accum0, &a[4], &b[6]);
119
120     mac(&accum2, &a[1], &b[1]);
121     mac(&accum1, &aa[1], &bb[1]);
122     mac(&accum0, &a[5], &b[5]);
123
124     mac(&accum2, &a[2], &b[0]);
125     mac(&accum1, &aa[2], &bb[0]);
126     mac(&accum0, &a[6], &b[4]);
127
128     accum1 -= accum2;
129     accum0 += accum2;
130
131     c[2] = ((uint64_t)(accum0)) & mask;
132     c[6] = ((uint64_t)(accum1)) & mask;
133
134     accum0 >>= 56;
135     accum1 >>= 56;
136
137     accum0 += c[3];
138     accum1 += c[7];
139     c[3] = ((uint64_t)(accum0)) & mask;
140     c[7] = ((uint64_t)(accum1)) & mask;
141
142     /* we could almost stop here, but it wouldn't be stable, so... */
143
144     accum0 >>= 56;
145     accum1 >>= 56;
146     c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1));
147     c[0] += ((uint64_t)(accum1));
148 }
149
150 void gf_mulw_unsigned(gf_s * __restrict__ cs, const gf as, uint32_t b)
151 {
152     const uint64_t *a = as->limb;
153     uint64_t *c = cs->limb;
154
155     __uint128_t accum0, accum4;
156     uint64_t mask = (1ull << 56) - 1;
157
158     accum0 = widemul_rm(b, &a[0]);
159     accum4 = widemul_rm(b, &a[4]);
160
161     c[0] = accum0 & mask;
162     accum0 >>= 56;
163     c[4] = accum4 & mask;
164     accum4 >>= 56;
165
166     mac_rm(&accum0, b, &a[1]);
167     mac_rm(&accum4, b, &a[5]);
168
169     c[1] = accum0 & mask;
170     accum0 >>= 56;
171     c[5] = accum4 & mask;
172     accum4 >>= 56;
173
174     mac_rm(&accum0, b, &a[2]);
175     mac_rm(&accum4, b, &a[6]);
176
177     c[2] = accum0 & mask;
178     accum0 >>= 56;
179     c[6] = accum4 & mask;
180     accum4 >>= 56;
181
182     mac_rm(&accum0, b, &a[3]);
183     mac_rm(&accum4, b, &a[7]);
184
185     c[3] = accum0 & mask;
186     accum0 >>= 56;
187     c[7] = accum4 & mask;
188     accum4 >>= 56;
189
190     accum0 += accum4 + c[4];
191     c[4] = accum0 & mask;
192     c[5] += accum0 >> 56;
193
194     accum4 += c[0];
195     c[0] = accum4 & mask;
196     c[1] += accum4 >> 56;
197 }
198
199 void gf_sqr(gf_s * __restrict__ cs, const gf as)
200 {
201     const uint64_t *a = as->limb;
202     uint64_t *c = cs->limb;
203     __uint128_t accum0 = 0, accum1 = 0, accum2;
204     uint64_t mask = (1ull << 56) - 1;
205     uint64_t aa[4] VECTOR_ALIGNED;
206
207     /* For some reason clang doesn't vectorize this without prompting? */
208     unsigned int i;
209     for (i = 0; i < sizeof(aa) / sizeof(uint64xn_t); i++) {
210         ((uint64xn_t *) aa)[i] =
211             ((const uint64xn_t *)a)[i] + ((const uint64xn_t *)(&a[4]))[i];
212     }
213
214     accum2 = widemul(&a[0], &a[3]);
215     accum0 = widemul(&aa[0], &aa[3]);
216     accum1 = widemul(&a[4], &a[7]);
217
218     mac(&accum2, &a[1], &a[2]);
219     mac(&accum0, &aa[1], &aa[2]);
220     mac(&accum1, &a[5], &a[6]);
221
222     accum0 -= accum2;
223     accum1 += accum2;
224
225     c[3] = ((uint64_t)(accum1)) << 1 & mask;
226     c[7] = ((uint64_t)(accum0)) << 1 & mask;
227
228     accum0 >>= 55;
229     accum1 >>= 55;
230
231     mac2(&accum0, &aa[1], &aa[3]);
232     mac2(&accum1, &a[5], &a[7]);
233     mac(&accum0, &aa[2], &aa[2]);
234     accum1 += accum0;
235
236     msb2(&accum0, &a[1], &a[3]);
237     mac(&accum1, &a[6], &a[6]);
238
239     accum2 = widemul(&a[0], &a[0]);
240     accum1 -= accum2;
241     accum0 += accum2;
242
243     msb(&accum0, &a[2], &a[2]);
244     mac(&accum1, &aa[0], &aa[0]);
245     mac(&accum0, &a[4], &a[4]);
246
247     c[0] = ((uint64_t)(accum0)) & mask;
248     c[4] = ((uint64_t)(accum1)) & mask;
249
250     accum0 >>= 56;
251     accum1 >>= 56;
252
253     accum2 = widemul2(&aa[2], &aa[3]);
254     msb2(&accum0, &a[2], &a[3]);
255     mac2(&accum1, &a[6], &a[7]);
256
257     accum1 += accum2;
258     accum0 += accum2;
259
260     accum2 = widemul2(&a[0], &a[1]);
261     mac2(&accum1, &aa[0], &aa[1]);
262     mac2(&accum0, &a[4], &a[5]);
263
264     accum1 -= accum2;
265     accum0 += accum2;
266
267     c[1] = ((uint64_t)(accum0)) & mask;
268     c[5] = ((uint64_t)(accum1)) & mask;
269
270     accum0 >>= 56;
271     accum1 >>= 56;
272
273     accum2 = widemul(&aa[3], &aa[3]);
274     msb(&accum0, &a[3], &a[3]);
275     mac(&accum1, &a[7], &a[7]);
276
277     accum1 += accum2;
278     accum0 += accum2;
279
280     accum2 = widemul2(&a[0], &a[2]);
281     mac2(&accum1, &aa[0], &aa[2]);
282     mac2(&accum0, &a[4], &a[6]);
283
284     mac(&accum2, &a[1], &a[1]);
285     mac(&accum1, &aa[1], &aa[1]);
286     mac(&accum0, &a[5], &a[5]);
287
288     accum1 -= accum2;
289     accum0 += accum2;
290
291     c[2] = ((uint64_t)(accum0)) & mask;
292     c[6] = ((uint64_t)(accum1)) & mask;
293
294     accum0 >>= 56;
295     accum1 >>= 56;
296
297     accum0 += c[3];
298     accum1 += c[7];
299     c[3] = ((uint64_t)(accum0)) & mask;
300     c[7] = ((uint64_t)(accum1)) & mask;
301
302     /* we could almost stop here, but it wouldn't be stable, so... */
303
304     accum0 >>= 56;
305     accum1 >>= 56;
306     c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1));
307     c[0] += ((uint64_t)(accum1));
308 }