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