Botan 3.11.0
Crypto and TLS for C&
mp_asmi.h
Go to the documentation of this file.
1/*
2* Lowest Level MPI Algorithms
3* (C) 1999-2010,2025 Jack Lloyd
4* 2006 Luca Piccarreta
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#ifndef BOTAN_MP_ASM_INTERNAL_H_
10#define BOTAN_MP_ASM_INTERNAL_H_
11
12#include <botan/compiler.h>
13#include <botan/types.h>
14#include <botan/internal/target_info.h>
15#include <concepts>
16
17#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
18 #include <botan/internal/donna128.h>
19#endif
20
21namespace Botan {
22
23// NOLINTBEGIN(*-macro-usage,*-no-assembler)
24
25#if defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_X86_64)
26 #define BOTAN_MP_USE_X86_64_ASM
27#endif
28
29#if defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_ARM64)
30 #define BOTAN_MP_USE_AARCH64_ASM
31#endif
32
33/*
34* Expressing an add with carry is sadly quite difficult in standard C/C++.
35*
36* Compilers will recognize various idioms and generate a reasonable carry
37* chain. Unfortunately which idioms the compiler will understand vary, so we
38* have to decide what to do based on the compiler. This is fragile; what will
39* work varies not just based on compiler but also version, target architecture,
40* and optimization flags.
41*/
42#if defined(__clang__)
43static constexpr bool use_dword_for_word_add = false;
44#else
45static constexpr bool use_dword_for_word_add = true;
46#endif
47
48/*
49* Concept for allowed multiprecision word types
50*/
51template <typename T>
52concept WordType = (std::same_as<T, uint32_t> || std::same_as<T, uint64_t>);
53
54template <WordType W>
55struct WordInfo {};
56
57template <>
58struct WordInfo<uint32_t> {
59 public:
60 static const constexpr size_t bytes = 4;
61 static const constexpr size_t bits = 32;
62 static const constexpr uint32_t max = 0xFFFFFFFF;
63 static const constexpr uint32_t top_bit = 0x80000000;
64
65 typedef uint64_t dword;
66 static const constexpr bool dword_is_native = true;
67};
68
69template <>
70struct WordInfo<uint64_t> {
71 public:
72 static const constexpr size_t bytes = 8;
73 static const constexpr size_t bits = 64;
74 static const constexpr uint64_t max = 0xFFFFFFFFFFFFFFFF;
75 static const constexpr uint64_t top_bit = 0x8000000000000000;
76
77#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
78 typedef uint128_t dword;
79 static const constexpr bool dword_is_native = true;
80#else
81 typedef donna128 dword;
82 static const constexpr bool dword_is_native = false;
83#endif
84};
85
86/*
87* Word Multiply/Add
88*/
89template <WordType W>
90inline constexpr auto word_madd2(W a, W b, W* c) -> W {
91#if defined(BOTAN_MP_USE_X86_64_ASM)
92 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
93 asm(R"(
94 mulq %[b]
95 addq %[c],%[a]
96 adcq $0,%[carry]
97 )"
98 : [a] "=a"(a), [b] "=rm"(b), [carry] "=&d"(*c)
99 : "0"(a), "1"(b), [c] "g"(*c)
100 : "cc");
101
102 return a;
103 }
104#elif defined(BOTAN_MP_USE_AARCH64_ASM)
105 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
106 W lo = 0;
107 W hi = 0;
108 asm(R"(
109 mul %[lo], %[a], %[b]
110 umulh %[hi], %[a], %[b]
111 adds %[lo], %[lo], %[c]
112 adc %[hi], %[hi], xzr
113 )"
114 : [lo] "=&r"(lo), [hi] "=&r"(hi)
115 : [a] "r"(a), [b] "r"(b), [c] "r"(*c)
116 : "cc");
117
118 *c = hi;
119 return lo;
120 }
121#endif
122
123 typedef typename WordInfo<W>::dword dword;
124 const dword s = dword(a) * b + *c;
125 *c = static_cast<W>(s >> WordInfo<W>::bits);
126 return static_cast<W>(s);
127}
128
129/*
130* Word Multiply/Add
131*/
132template <WordType W>
133inline constexpr auto word_madd3(W a, W b, W c, W* d) -> W {
134#if defined(BOTAN_MP_USE_X86_64_ASM)
135 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
136 asm(R"(
137 mulq %[b]
138
139 addq %[c],%[a]
140 adcq $0,%[carry]
141
142 addq %[d],%[a]
143 adcq $0,%[carry]
144 )"
145 : [a] "=a"(a), [b] "=rm"(b), [carry] "=&d"(*d)
146 : "0"(a), "1"(b), [c] "g"(c), [d] "g"(*d)
147 : "cc");
148
149 return a;
150 }
151#elif defined(BOTAN_MP_USE_AARCH64_ASM)
152 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
153 W lo = 0;
154 W hi = 0;
155 asm(R"(
156 mul %[lo], %[a], %[b]
157 umulh %[hi], %[a], %[b]
158 adds %[lo], %[lo], %[c]
159 adc %[hi], %[hi], xzr
160 adds %[lo], %[lo], %[d]
161 adc %[hi], %[hi], xzr
162 )"
163 : [lo] "=&r"(lo), [hi] "=&r"(hi)
164 : [a] "r"(a), [b] "r"(b), [c] "r"(c), [d] "r"(*d)
165 : "cc");
166
167 *d = hi;
168 return lo;
169 }
170#endif
171
172 typedef typename WordInfo<W>::dword dword;
173 const dword s = dword(a) * b + c + *d;
174 *d = static_cast<W>(s >> WordInfo<W>::bits);
175 return static_cast<W>(s);
176}
177
178#if defined(BOTAN_MP_USE_X86_64_ASM)
179
180 #define ASM(x) x "\n\t"
181
182 #define DO_8_TIMES(MACRO, ARG) \
183 MACRO(ARG, 0) \
184 MACRO(ARG, 1) \
185 MACRO(ARG, 2) \
186 MACRO(ARG, 3) \
187 MACRO(ARG, 4) \
188 MACRO(ARG, 5) \
189 MACRO(ARG, 6) \
190 MACRO(ARG, 7)
191
192 #define ADDSUB2_OP(OPERATION, INDEX) \
193 ASM("movq 8*" #INDEX "(%[y]), %[carry]") \
194 ASM(OPERATION " %[carry], 8*" #INDEX "(%[x])")
195
196 #define ADDSUB3_OP(OPERATION, INDEX) \
197 ASM("movq 8*" #INDEX "(%[x]), %[carry]") \
198 ASM(OPERATION " 8*" #INDEX "(%[y]), %[carry]") \
199 ASM("movq %[carry], 8*" #INDEX "(%[z])")
200
201 #define LINMUL_OP(WRITE_TO, INDEX) \
202 ASM("movq 8*" #INDEX "(%[x]),%%rax") \
203 ASM("mulq %[y]") \
204 ASM("addq %[carry],%%rax") \
205 ASM("adcq $0,%%rdx") \
206 ASM("movq %%rdx,%[carry]") \
207 ASM("movq %%rax, 8*" #INDEX "(%[" WRITE_TO "])")
208
209 #define MULADD_OP(IGNORED, INDEX) \
210 ASM("movq 8*" #INDEX "(%[x]),%%rax") \
211 ASM("mulq %[y]") \
212 ASM("addq %[carry],%%rax") \
213 ASM("adcq $0,%%rdx") \
214 ASM("addq 8*" #INDEX "(%[z]),%%rax") \
215 ASM("adcq $0,%%rdx") \
216 ASM("movq %%rdx,%[carry]") \
217 ASM("movq %%rax, 8*" #INDEX " (%[z])")
218
219 #define ADD_OR_SUBTRACT(CORE_CODE) \
220 ASM("rorq %[carry]") \
221 CORE_CODE \
222 ASM("sbbq %[carry],%[carry]") \
223 ASM("negq %[carry]")
224
225#endif
226
227/*
228* Word Addition
229*/
230template <WordType W>
231inline constexpr auto word_add(W x, W y, W* carry) -> W {
232#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_addc)
233 if(!std::is_constant_evaluated()) {
234 if constexpr(std::same_as<W, unsigned int>) {
235 return __builtin_addc(x, y, *carry & 1, carry);
236 } else if constexpr(std::same_as<W, unsigned long>) {
237 return __builtin_addcl(x, y, *carry & 1, carry);
238 } else if constexpr(std::same_as<W, unsigned long long>) {
239 return __builtin_addcll(x, y, *carry & 1, carry);
240 }
241 }
242#endif
243
244 if constexpr(WordInfo<W>::dword_is_native && use_dword_for_word_add) {
245 /*
246 TODO(Botan4) this is largely a performance hack for GCCs that don't
247 support __builtin_addc, if we increase the minimum supported version of
248 GCC to GCC 14 then we can remove this and not worry about it
249 */
250 const W cb = *carry & 1;
251 const auto s = typename WordInfo<W>::dword(x) + y + cb;
252 *carry = static_cast<W>(s >> WordInfo<W>::bits);
253 return static_cast<W>(s);
254 } else {
255 const W cb = *carry & 1;
256 W z = x + y;
257 W c1 = (z < x);
258 z += cb;
259 *carry = c1 | (z < cb);
260 return z;
261 }
262}
263
264/*
265* Eight Word Block Addition, Two Argument
266*/
267template <WordType W>
268inline constexpr auto word8_add2(W x[8], const W y[8], W carry) -> W {
269#if defined(BOTAN_MP_USE_X86_64_ASM)
270 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
271 asm volatile(ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcq"))
272 : [carry] "=r"(carry)
273 : [x] "r"(x), [y] "r"(y), "0"(carry)
274 : "cc", "memory");
275 return carry;
276 }
277#endif
278
279 x[0] = word_add(x[0], y[0], &carry);
280 x[1] = word_add(x[1], y[1], &carry);
281 x[2] = word_add(x[2], y[2], &carry);
282 x[3] = word_add(x[3], y[3], &carry);
283 x[4] = word_add(x[4], y[4], &carry);
284 x[5] = word_add(x[5], y[5], &carry);
285 x[6] = word_add(x[6], y[6], &carry);
286 x[7] = word_add(x[7], y[7], &carry);
287 return carry;
288}
289
290/*
291* Eight Word Block Addition, Three Argument
292*/
293template <WordType W>
294inline constexpr auto word8_add3(W z[8], const W x[8], const W y[8], W carry) -> W {
295#if defined(BOTAN_MP_USE_X86_64_ASM)
296 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
297 asm volatile(ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcq"))
298 : [carry] "=r"(carry)
299 : [x] "r"(x), [y] "r"(y), [z] "r"(z), "0"(carry)
300 : "cc", "memory");
301 return carry;
302 }
303#endif
304
305 z[0] = word_add(x[0], y[0], &carry);
306 z[1] = word_add(x[1], y[1], &carry);
307 z[2] = word_add(x[2], y[2], &carry);
308 z[3] = word_add(x[3], y[3], &carry);
309 z[4] = word_add(x[4], y[4], &carry);
310 z[5] = word_add(x[5], y[5], &carry);
311 z[6] = word_add(x[6], y[6], &carry);
312 z[7] = word_add(x[7], y[7], &carry);
313 return carry;
314}
315
316/*
317* Word Subtraction
318*/
319template <WordType W>
320inline constexpr auto word_sub(W x, W y, W* carry) -> W {
321#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_subc)
322 if(!std::is_constant_evaluated()) {
323 if constexpr(std::same_as<W, unsigned int>) {
324 return __builtin_subc(x, y, *carry & 1, carry);
325 } else if constexpr(std::same_as<W, unsigned long>) {
326 return __builtin_subcl(x, y, *carry & 1, carry);
327 } else if constexpr(std::same_as<W, unsigned long long>) {
328 return __builtin_subcll(x, y, *carry & 1, carry);
329 }
330 }
331#endif
332
333 const W cb = *carry & 1;
334 W t0 = x - y;
335 W c1 = (t0 > x);
336 W z = t0 - cb;
337 *carry = c1 | (z > t0);
338 return z;
339}
340
341/*
342* Eight Word Block Subtraction, Two Argument
343*/
344template <WordType W>
345inline constexpr auto word8_sub2(W x[8], const W y[8], W carry) -> W {
346#if defined(BOTAN_MP_USE_X86_64_ASM)
347 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
348 asm(ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbq"))
349 : [carry] "=r"(carry)
350 : [x] "r"(x), [y] "r"(y), "0"(carry)
351 : "cc", "memory");
352 return carry;
353 }
354#endif
355
356 x[0] = word_sub(x[0], y[0], &carry);
357 x[1] = word_sub(x[1], y[1], &carry);
358 x[2] = word_sub(x[2], y[2], &carry);
359 x[3] = word_sub(x[3], y[3], &carry);
360 x[4] = word_sub(x[4], y[4], &carry);
361 x[5] = word_sub(x[5], y[5], &carry);
362 x[6] = word_sub(x[6], y[6], &carry);
363 x[7] = word_sub(x[7], y[7], &carry);
364 return carry;
365}
366
367/*
368* Eight Word Block Subtraction, Three Argument
369*/
370template <WordType W>
371inline constexpr auto word8_sub3(W z[8], const W x[8], const W y[8], W carry) -> W {
372#if defined(BOTAN_MP_USE_X86_64_ASM)
373 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
374 asm volatile(ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbq"))
375 : [carry] "=r"(carry)
376 : [x] "r"(x), [y] "r"(y), [z] "r"(z), "0"(carry)
377 : "cc", "memory");
378 return carry;
379 }
380#endif
381
382 z[0] = word_sub(x[0], y[0], &carry);
383 z[1] = word_sub(x[1], y[1], &carry);
384 z[2] = word_sub(x[2], y[2], &carry);
385 z[3] = word_sub(x[3], y[3], &carry);
386 z[4] = word_sub(x[4], y[4], &carry);
387 z[5] = word_sub(x[5], y[5], &carry);
388 z[6] = word_sub(x[6], y[6], &carry);
389 z[7] = word_sub(x[7], y[7], &carry);
390 return carry;
391}
392
393/*
394* Eight Word Block Linear Multiplication
395*/
396template <WordType W>
397inline constexpr auto word8_linmul3(W z[8], const W x[8], W y, W carry) -> W {
398#if defined(BOTAN_MP_USE_X86_64_ASM)
399 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
400 asm(DO_8_TIMES(LINMUL_OP, "z")
401 : [carry] "=r"(carry)
402 : [z] "r"(z), [x] "r"(x), [y] "rm"(y), "0"(carry)
403 : "cc", "%rax", "%rdx");
404 return carry;
405 }
406#endif
407
408 z[0] = word_madd2(x[0], y, &carry);
409 z[1] = word_madd2(x[1], y, &carry);
410 z[2] = word_madd2(x[2], y, &carry);
411 z[3] = word_madd2(x[3], y, &carry);
412 z[4] = word_madd2(x[4], y, &carry);
413 z[5] = word_madd2(x[5], y, &carry);
414 z[6] = word_madd2(x[6], y, &carry);
415 z[7] = word_madd2(x[7], y, &carry);
416 return carry;
417}
418
419/*
420* Eight Word Block Multiply/Add
421*/
422template <WordType W>
423inline constexpr auto word8_madd3(W z[8], const W x[8], W y, W carry) -> W {
424#if defined(BOTAN_MP_USE_X86_64_ASM)
425 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
426 asm(DO_8_TIMES(MULADD_OP, "")
427 : [carry] "=r"(carry)
428 : [z] "r"(z), [x] "r"(x), [y] "rm"(y), "0"(carry)
429 : "cc", "%rax", "%rdx");
430 return carry;
431 }
432#endif
433
434 z[0] = word_madd3(x[0], y, z[0], &carry);
435 z[1] = word_madd3(x[1], y, z[1], &carry);
436 z[2] = word_madd3(x[2], y, z[2], &carry);
437 z[3] = word_madd3(x[3], y, z[3], &carry);
438 z[4] = word_madd3(x[4], y, z[4], &carry);
439 z[5] = word_madd3(x[5], y, z[5], &carry);
440 z[6] = word_madd3(x[6], y, z[6], &carry);
441 z[7] = word_madd3(x[7], y, z[7], &carry);
442 return carry;
443}
444
445/**
446* Helper for 3-word accumulators
447*
448* A number of algorithms especially Comba multiplication and
449* Montgomery reduction can take advantage of wide accumulators, which
450* consume inputs via addition with outputs extracted from the low
451* bits.
452*/
453template <WordType W>
454class word3 final {
455#if defined(__BITINT_MAXWIDTH__) && (__BITINT_MAXWIDTH__ >= 3 * 64)
456
457 public:
458 constexpr word3() : m_w(0) {}
459
460 inline constexpr void mul(W x, W y) { m_w += static_cast<W3>(x) * y; }
461
462 inline constexpr void mul_x2(W x, W y) { m_w += static_cast<W3>(x) * y * 2; }
463
464 inline constexpr void add(W x) { m_w += x; }
465
466 inline constexpr W extract() {
467 W r = static_cast<W>(m_w);
468 m_w >>= WordInfo<W>::bits;
469 return r;
470 }
471
472 inline constexpr W monty_step(W p0, W p_dash) {
473 const W w0 = static_cast<W>(m_w);
474 const W r = w0 * p_dash;
475 mul(r, p0);
476 m_w >>= WordInfo<W>::bits;
477 return r;
478 }
479
480 inline constexpr W monty_step_pdash1() {
481 const W r = static_cast<W>(m_w);
482 m_w >>= WordInfo<W>::bits;
483 m_w += static_cast<W3>(r);
484 return r;
485 }
486
487 private:
488 __extension__ typedef unsigned _BitInt(WordInfo<W>::bits * 3) W3;
489 W3 m_w;
490#else
491
492 public:
493 constexpr word3() : m_w0(0), m_w1(0), m_w2(0) {}
494
495 inline constexpr void mul(W x, W y) {
496 #if defined(BOTAN_MP_USE_X86_64_ASM)
497 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
498 W z0 = 0;
499 W z1 = 0;
500
501 asm("mulq %[y]" : "=a"(z0), "=d"(z1) : "a"(x), [y] "rm"(y) : "cc");
502
503 asm(R"(
504 addq %[z0],%[w0]
505 adcq %[z1],%[w1]
506 adcq $0,%[w2]
507 )"
508 : [w0] "=r"(m_w0), [w1] "=r"(m_w1), [w2] "=r"(m_w2)
509 : [z0] "r"(z0), [z1] "r"(z1), "0"(m_w0), "1"(m_w1), "2"(m_w2)
510 : "cc");
511 return;
512 }
513 #elif defined(BOTAN_MP_USE_AARCH64_ASM)
514 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
515 W t0 = 0;
516 W t1 = 0;
517 asm(R"(
518 mul %[t0], %[x], %[y]
519 umulh %[t1], %[x], %[y]
520 adds %[w0], %[w0], %[t0]
521 adcs %[w1], %[w1], %[t1]
522 adc %[w2], %[w2], xzr
523 )"
524 : [w0] "+r"(m_w0), [w1] "+r"(m_w1), [w2] "+r"(m_w2), [t0] "=&r"(t0), [t1] "=&r"(t1)
525 : [x] "r"(x), [y] "r"(y)
526 : "cc");
527 return;
528 }
529 #endif
530
531 typedef typename WordInfo<W>::dword dword;
532 const auto z = dword(x) * y;
533 const auto z0 = static_cast<W>(z);
534 const auto z1 = static_cast<W>(z >> WordInfo<W>::bits);
535
536 W carry = 0;
537 m_w0 = word_add(m_w0, z0, &carry);
538 m_w1 = word_add(m_w1, z1, &carry);
539 m_w2 += carry;
540 }
541
542 inline constexpr void mul_x2(W x, W y) {
543 #if defined(BOTAN_MP_USE_X86_64_ASM)
544 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
545 W z0 = 0;
546 W z1 = 0;
547
548 asm("mulq %[y]" : "=a"(z0), "=d"(z1) : "a"(x), [y] "rm"(y) : "cc");
549
550 asm(R"(
551 addq %[z0],%[w0]
552 adcq %[z1],%[w1]
553 adcq $0,%[w2]
554
555 addq %[z0],%[w0]
556 adcq %[z1],%[w1]
557 adcq $0,%[w2]
558 )"
559 : [w0] "=r"(m_w0), [w1] "=r"(m_w1), [w2] "=r"(m_w2)
560 : [z0] "r"(z0), [z1] "r"(z1), "0"(m_w0), "1"(m_w1), "2"(m_w2)
561 : "cc");
562 return;
563 }
564 #elif defined(BOTAN_MP_USE_AARCH64_ASM)
565 if(std::same_as<W, uint64_t> && !std::is_constant_evaluated()) {
566 W t0 = 0;
567 W t1 = 0;
568 asm(R"(
569 mul %[t0], %[x], %[y]
570 umulh %[t1], %[x], %[y]
571 adds %[w0], %[w0], %[t0]
572 adcs %[w1], %[w1], %[t1]
573 adc %[w2], %[w2], xzr
574 adds %[w0], %[w0], %[t0]
575 adcs %[w1], %[w1], %[t1]
576 adc %[w2], %[w2], xzr
577 )"
578 : [w0] "+r"(m_w0), [w1] "+r"(m_w1), [w2] "+r"(m_w2), [t0] "=&r"(t0), [t1] "=&r"(t1)
579 : [x] "r"(x), [y] "r"(y)
580 : "cc");
581 return;
582 }
583 #endif
584
585 typedef typename WordInfo<W>::dword dword;
586 const auto z = dword(x) * y;
587 const auto z0 = static_cast<W>(z);
588 const auto z1 = static_cast<W>(z >> WordInfo<W>::bits);
589
590 W carry = 0;
591 m_w0 = word_add(m_w0, z0, &carry);
592 m_w1 = word_add(m_w1, z1, &carry);
593 m_w2 += carry;
594
595 carry = 0;
596 m_w0 = word_add(m_w0, z0, &carry);
597 m_w1 = word_add(m_w1, z1, &carry);
598 m_w2 += carry;
599 }
600
601 inline constexpr void add(W x) {
602 constexpr W z = 0;
603
604 W carry = 0;
605 m_w0 = word_add(m_w0, x, &carry);
606 m_w1 = word_add(m_w1, z, &carry);
607 m_w2 += carry;
608 }
609
610 inline constexpr W extract() {
611 W r = m_w0;
612 m_w0 = m_w1;
613 m_w1 = m_w2;
614 m_w2 = 0;
615 return r;
616 }
617
618 inline constexpr W monty_step(W p0, W p_dash) {
619 W r = m_w0 * p_dash;
620 mul(r, p0);
621 m_w0 = m_w1;
622 m_w1 = m_w2;
623 m_w2 = 0;
624 return r;
625 }
626
627 inline constexpr W monty_step_pdash1() {
628 // If p_dash == 1 then p[0] = -1 and everything simplifies
629 const W r = m_w0;
630 m_w0 += m_w1;
631 m_w1 = m_w2 + (m_w0 < m_w1);
632 m_w2 = 0;
633 return r;
634 }
635
636 private:
637 W m_w0;
638 W m_w1;
639 W m_w2;
640#endif
641};
642
643#if defined(ASM)
644 #undef ASM
645 #undef DO_8_TIMES
646 #undef ADD_OR_SUBTRACT
647 #undef ADDSUB2_OP
648 #undef ADDSUB3_OP
649 #undef LINMUL_OP
650 #undef MULADD_OP
651#endif
652
653// NOLINTEND(*-macro-usage,*-no-assembler)
654
655} // namespace Botan
656
657#endif
constexpr void add(W x)
Definition mp_asmi.h:601
constexpr W monty_step(W p0, W p_dash)
Definition mp_asmi.h:618
constexpr word3()
Definition mp_asmi.h:493
constexpr W extract()
Definition mp_asmi.h:610
constexpr void mul(W x, W y)
Definition mp_asmi.h:495
constexpr W monty_step_pdash1()
Definition mp_asmi.h:627
constexpr void mul_x2(W x, W y)
Definition mp_asmi.h:542
constexpr auto word8_sub3(W z[8], const W x[8], const W y[8], W carry) -> W
Definition mp_asmi.h:371
constexpr auto word_sub(W x, W y, W *carry) -> W
Definition mp_asmi.h:320
constexpr auto word_add(W x, W y, W *carry) -> W
Definition mp_asmi.h:231
constexpr auto word8_madd3(W z[8], const W x[8], W y, W carry) -> W
Definition mp_asmi.h:423
constexpr auto word8_add3(W z[8], const W x[8], const W y[8], W carry) -> W
Definition mp_asmi.h:294
constexpr auto word8_sub2(W x[8], const W y[8], W carry) -> W
Definition mp_asmi.h:345
constexpr auto word_madd2(W a, W b, W *c) -> W
Definition mp_asmi.h:90
void carry(int64_t &h0, int64_t &h1)
constexpr auto word8_add2(W x[8], const W y[8], W carry) -> W
Definition mp_asmi.h:268
constexpr auto word8_linmul3(W z[8], const W x[8], W y, W carry) -> W
Definition mp_asmi.h:397
constexpr auto word_madd3(W a, W b, W c, W *d) -> W
Definition mp_asmi.h:133
static const constexpr bool dword_is_native
Definition mp_asmi.h:66
static const constexpr uint32_t top_bit
Definition mp_asmi.h:63
static const constexpr size_t bytes
Definition mp_asmi.h:60
static const constexpr size_t bits
Definition mp_asmi.h:61
static const constexpr uint32_t max
Definition mp_asmi.h:62
static const constexpr size_t bytes
Definition mp_asmi.h:72
static const constexpr bool dword_is_native
Definition mp_asmi.h:82
static const constexpr size_t bits
Definition mp_asmi.h:73
static const constexpr uint64_t max
Definition mp_asmi.h:74
static const constexpr uint64_t top_bit
Definition mp_asmi.h:75