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