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