cca3f81c17ee78f87b7700aade1a722f7ca25077
[openssl.git] / crypto / ec / curve448 / arch_x86_64 / arch_intrinsics.h
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright 2014-2016 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 #ifndef __ARCH_X86_64_ARCH_INTRINSICS_H__
13 #define __ARCH_X86_64_ARCH_INTRINSICS_H__
14
15 #define ARCH_WORD_BITS 64
16
17 #include <openssl/e_os2.h>
18
19 /* FUTURE: autogenerate */
20 static __inline__ __uint128_t widemul(const uint64_t *a, const uint64_t *b)
21 {
22   uint64_t c, d;
23
24   #ifndef __BMI2__
25       __asm__ volatile
26           ("movq %[a], %%rax;"
27            "mulq %[b];"
28            : [c]"=&a"(c), [d]"=d"(d)
29            : [b]"m"(*b), [a]"m"(*a)
30            : "cc");
31   #else
32       __asm__ volatile
33           ("movq %[a], %%rdx;"
34            "mulx %[b], %[c], %[d];"
35            : [c]"=r"(c), [d]"=r"(d)
36            : [b]"m"(*b), [a]"m"(*a)
37            : "rdx");
38   #endif
39   return (((__uint128_t)(d)) << 64) | c;
40 }
41
42 static __inline__ __uint128_t widemul_rm(uint64_t a, const uint64_t *b)
43 {
44   uint64_t c, d;
45
46   #ifndef __BMI2__
47       __asm__ volatile
48           ("movq %[a], %%rax;"
49            "mulq %[b];"
50            : [c]"=&a"(c), [d]"=d"(d)
51            : [b]"m"(*b), [a]"r"(a)
52            : "cc");
53   #else
54       __asm__ volatile
55           ("mulx %[b], %[c], %[d];"
56            : [c]"=r"(c), [d]"=r"(d)
57            : [b]"m"(*b), [a]"d"(a));
58   #endif
59   return (((__uint128_t)(d)) << 64) | c;
60 }
61
62 static __inline__ __uint128_t widemul_rr(uint64_t a, uint64_t b)
63 {
64   uint64_t c, d;
65
66   #ifndef __BMI2__
67       __asm__ volatile
68           ("mulq %[b];"
69            : [c]"=a"(c), [d]"=d"(d)
70            : [b]"r"(b), "a"(a)
71            : "cc");
72   #else
73       __asm__ volatile
74           ("mulx %[b], %[c], %[d];"
75            : [c]"=r"(c), [d]"=r"(d)
76            : [b]"r"(b), [a]"d"(a));
77   #endif
78   return (((__uint128_t)(d)) << 64) | c;
79 }
80
81 static __inline__ __uint128_t widemul2(const uint64_t *a, const uint64_t *b)
82 {
83   uint64_t c, d;
84
85   #ifndef __BMI2__
86       __asm__ volatile
87           ("movq %[a], %%rax; "
88            "addq %%rax, %%rax; "
89            "mulq %[b];"
90            : [c]"=&a"(c), [d]"=d"(d)
91            : [b]"m"(*b), [a]"m"(*a)
92            : "cc");
93   #else
94       __asm__ volatile
95           ("movq %[a], %%rdx;"
96            "leaq (,%%rdx,2), %%rdx;"
97            "mulx %[b], %[c], %[d];"
98            : [c]"=r"(c), [d]"=r"(d)
99            : [b]"m"(*b), [a]"m"(*a)
100            : "rdx");
101   #endif
102   return (((__uint128_t)(d)) << 64) | c;
103 }
104
105 static __inline__ void mac(__uint128_t *acc, const uint64_t *a,
106                            const uint64_t *b)
107 {
108   uint64_t lo = *acc, hi = *acc >> 64;
109   
110   #ifdef __BMI2__
111       uint64_t c,d;
112       __asm__ volatile
113           ("movq %[a], %%rdx; "
114            "mulx %[b], %[c], %[d]; "
115            "addq %[c], %[lo]; "
116            "adcq %[d], %[hi]; "
117            : [c]"=&r"(c), [d]"=&r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
118            : [b]"m"(*b), [a]"m"(*a)
119            : "rdx", "cc");
120   #else
121       __asm__ volatile
122           ("movq %[a], %%rax; "
123            "mulq %[b]; "
124            "addq %%rax, %[lo]; "
125            "adcq %%rdx, %[hi]; "
126            : [lo]"+r"(lo), [hi]"+r"(hi)
127            : [b]"m"(*b), [a]"m"(*a)
128            : "rax", "rdx", "cc");
129   #endif
130   
131   *acc = (((__uint128_t)(hi)) << 64) | lo;
132 }
133
134 static __inline__ void macac(__uint128_t *acc, __uint128_t *acc2,
135                              const uint64_t *a, const uint64_t *b)
136 {
137   uint64_t lo = *acc, hi = *acc >> 64;
138   uint64_t lo2 = *acc2, hi2 = *acc2 >> 64;
139   
140   #ifdef __BMI2__
141       uint64_t c,d;
142       __asm__ volatile
143           ("movq %[a], %%rdx; "
144            "mulx %[b], %[c], %[d]; "
145            "addq %[c], %[lo]; "
146            "adcq %[d], %[hi]; "
147            "addq %[c], %[lo2]; "
148            "adcq %[d], %[hi2]; "
149            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi), [lo2]"+r"(lo2), [hi2]"+r"(hi2)
150            : [b]"m"(*b), [a]"m"(*a)
151            : "rdx", "cc");
152   #else
153       __asm__ volatile
154           ("movq %[a], %%rax; "
155            "mulq %[b]; "
156            "addq %%rax, %[lo]; "
157            "adcq %%rdx, %[hi]; "
158            "addq %%rax, %[lo2]; "
159            "adcq %%rdx, %[hi2]; "
160            : [lo]"+r"(lo), [hi]"+r"(hi), [lo2]"+r"(lo2), [hi2]"+r"(hi2)
161            : [b]"m"(*b), [a]"m"(*a)
162            : "rax", "rdx", "cc");
163   #endif
164   
165   *acc = (((__uint128_t)(hi)) << 64) | lo;
166   *acc2 = (((__uint128_t)(hi2)) << 64) | lo2;
167 }
168
169 static __inline__ void mac_rm(__uint128_t *acc, uint64_t a, const uint64_t *b)
170 {
171   uint64_t lo = *acc, hi = *acc >> 64;
172   
173   #ifdef __BMI2__
174       uint64_t c,d;
175       __asm__ volatile
176           ("mulx %[b], %[c], %[d]; "
177            "addq %[c], %[lo]; "
178            "adcq %[d], %[hi]; "
179            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
180            : [b]"m"(*b), [a]"d"(a)
181            : "cc");
182   #else
183       __asm__ volatile
184           ("movq %[a], %%rax; "
185            "mulq %[b]; "
186            "addq %%rax, %[lo]; "
187            "adcq %%rdx, %[hi]; "
188            : [lo]"+r"(lo), [hi]"+r"(hi)
189            : [b]"m"(*b), [a]"r"(a)
190            : "rax", "rdx", "cc");
191   #endif
192   
193   *acc = (((__uint128_t)(hi)) << 64) | lo;
194 }
195
196 static __inline__ void mac_rr(__uint128_t *acc, uint64_t a, const uint64_t b)
197 {
198   uint64_t lo = *acc, hi = *acc >> 64;
199   
200   #ifdef __BMI2__
201       uint64_t c,d;
202       __asm__ volatile
203           ("mulx %[b], %[c], %[d]; "
204            "addq %[c], %[lo]; "
205            "adcq %[d], %[hi]; "
206            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
207            : [b]"r"(b), [a]"d"(a)
208            : "cc");
209   #else
210       __asm__ volatile
211           ("mulq %[b]; "
212            "addq %%rax, %[lo]; "
213            "adcq %%rdx, %[hi]; "
214            : [lo]"+r"(lo), [hi]"+r"(hi), "+a"(a)
215            : [b]"r"(b)
216            : "rdx", "cc");
217   #endif
218   
219   *acc = (((__uint128_t)(hi)) << 64) | lo;
220 }
221
222 static __inline__ void mac2(__uint128_t *acc, const uint64_t *a,
223                             const uint64_t *b)
224 {
225   uint64_t lo = *acc, hi = *acc >> 64;
226   
227   #ifdef __BMI2__
228       uint64_t c,d;
229       __asm__ volatile
230           ("movq %[a], %%rdx; "
231            "addq %%rdx, %%rdx; "
232            "mulx %[b], %[c], %[d]; "
233            "addq %[c], %[lo]; "
234            "adcq %[d], %[hi]; "
235            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
236            : [b]"m"(*b), [a]"m"(*a)
237            : "rdx", "cc");
238   #else
239       __asm__ volatile
240           ("movq %[a], %%rax; "
241            "addq %%rax, %%rax; "
242            "mulq %[b]; "
243            "addq %%rax, %[lo]; "
244            "adcq %%rdx, %[hi]; "
245            : [lo]"+r"(lo), [hi]"+r"(hi)
246            : [b]"m"(*b), [a]"m"(*a)
247            : "rax", "rdx", "cc");
248   #endif
249   
250   *acc = (((__uint128_t)(hi)) << 64) | lo;
251 }
252
253 static __inline__ void msb(__uint128_t *acc, const uint64_t *a,
254                            const uint64_t *b)
255 {
256   uint64_t lo = *acc, hi = *acc >> 64;
257
258   #ifdef __BMI2__
259       uint64_t c,d;
260       __asm__ volatile
261           ("movq %[a], %%rdx; "
262            "mulx %[b], %[c], %[d]; "
263            "subq %[c], %[lo]; "
264            "sbbq %[d], %[hi]; "
265            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
266            : [b]"m"(*b), [a]"m"(*a)
267            : "rdx", "cc");
268   #else
269       __asm__ volatile
270           ("movq %[a], %%rax; "
271            "mulq %[b]; "
272            "subq %%rax, %[lo]; "
273            "sbbq %%rdx, %[hi]; "
274            : [lo]"+r"(lo), [hi]"+r"(hi)
275            : [b]"m"(*b), [a]"m"(*a)
276            : "rax", "rdx", "cc");
277   #endif
278   *acc = (((__uint128_t)(hi)) << 64) | lo;
279 }
280
281 static __inline__ void msb2(__uint128_t *acc, const uint64_t *a,
282                             const uint64_t *b)
283 {
284   uint64_t lo = *acc, hi = *acc >> 64;
285
286   #ifdef __BMI2__
287       uint64_t c,d;
288       __asm__ volatile
289           ("movq %[a], %%rdx; "
290            "addq %%rdx, %%rdx; "
291            "mulx %[b], %[c], %[d]; "
292            "subq %[c], %[lo]; "
293            "sbbq %[d], %[hi]; "
294            : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
295            : [b]"m"(*b), [a]"m"(*a)
296            : "rdx", "cc");
297   #else
298       __asm__ volatile
299           ("movq %[a], %%rax; "
300            "addq %%rax, %%rax; "
301            "mulq %[b]; "
302            "subq %%rax, %[lo]; "
303            "sbbq %%rdx, %[hi]; "
304            : [lo]"+r"(lo), [hi]"+r"(hi)
305            : [b]"m"(*b), [a]"m"(*a)
306            : "rax", "rdx", "cc");
307   #endif
308   *acc = (((__uint128_t)(hi))<<64) | lo;
309   
310 }
311
312 static __inline__ void mrs(__uint128_t *acc, const uint64_t *a,
313                            const uint64_t *b)
314 {
315   uint64_t c,d, lo = *acc, hi = *acc >> 64;
316   __asm__ volatile
317       ("movq %[a], %%rdx; "
318        "mulx %[b], %[c], %[d]; "
319        "subq %[lo], %[c]; "
320        "sbbq %[hi], %[d]; "
321        : [c]"=r"(c), [d]"=r"(d), [lo]"+r"(lo), [hi]"+r"(hi)
322        : [b]"m"(*b), [a]"m"(*a)
323        : "rdx", "cc");
324   *acc = (((__uint128_t)(d)) << 64) | c;
325 }
326
327 static __inline__ uint64_t word_is_zero(uint64_t x)
328 {
329   __asm__ volatile("neg %0; sbb %0, %0;" : "+r"(x));
330   return ~x;
331 }
332
333 static inline uint64_t shrld(__uint128_t x, int n)
334 {
335     return x >> n;
336 }
337
338 #endif /* __ARCH_X86_64_ARCH_INTRINSICS_H__ */