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