summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/math/mp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/math/mp')
-rw-r--r--comm/third_party/botan/src/lib/math/mp/info.txt10
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_asmi.h611
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_comba.cpp2211
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_core.h819
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_karat.cpp408
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_madd.h146
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_monty.cpp133
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_monty.h31
-rw-r--r--comm/third_party/botan/src/lib/math/mp/mp_monty_n.cpp2614
9 files changed, 6983 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/math/mp/info.txt b/comm/third_party/botan/src/lib/math/mp/info.txt
new file mode 100644
index 0000000000..cee4325ed8
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/info.txt
@@ -0,0 +1,10 @@
+<defines>
+BIGINT_MP -> 20151225
+</defines>
+
+<header:internal>
+mp_core.h
+mp_madd.h
+mp_asmi.h
+mp_monty.h
+</header:internal>
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_asmi.h b/comm/third_party/botan/src/lib/math/mp/mp_asmi.h
new file mode 100644
index 0000000000..e1518d51c7
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_asmi.h
@@ -0,0 +1,611 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2010 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H_
+#define BOTAN_MP_ASM_INTERNAL_H_
+
+#include <botan/internal/mp_madd.h>
+
+namespace Botan {
+
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movl 4*" #INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 4*" #INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 4*" #INDEX "(%[y]), %[carry]") \
+ ASM("movl %[carry], 4*" #INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" #INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("addl 4*" #INDEX "(%[z]),%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" #INDEX " (%[z])")
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorl %[carry]") \
+ CORE_CODE \
+ ASM("sbbl %[carry],%[carry]") \
+ ASM("negl %[carry]")
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movq 8*" #INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 8*" #INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 8*" #INDEX "(%[y]), %[carry]") \
+ ASM("movq %[carry], 8*" #INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" #INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("addq 8*" #INDEX "(%[z]),%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" #INDEX " (%[z])")
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorq %[carry]") \
+ CORE_CODE \
+ ASM("sbbq %[carry],%[carry]") \
+ ASM("negq %[carry]")
+
+#endif
+
+#if defined(ADD_OR_SUBTRACT)
+
+#define ASM(x) x "\n\t"
+
+#define DO_8_TIMES(MACRO, ARG) \
+ MACRO(ARG, 0) \
+ MACRO(ARG, 1) \
+ MACRO(ARG, 2) \
+ MACRO(ARG, 3) \
+ MACRO(ARG, 4) \
+ MACRO(ARG, 5) \
+ MACRO(ARG, 6) \
+ MACRO(ARG, 7)
+
+#endif
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+
+#else
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+#endif
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#else
+ x[0] = word_add(x[0], y[0], &carry);
+ x[1] = word_add(x[1], y[1], &carry);
+ x[2] = word_add(x[2], y[2], &carry);
+ x[3] = word_add(x[3], y[3], &carry);
+ x[4] = word_add(x[4], y[4], &carry);
+ x[5] = word_add(x[5], y[5], &carry);
+ x[6] = word_add(x[6], y[6], &carry);
+ x[7] = word_add(x[7], y[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#else
+ z[0] = word_add(x[0], y[0], &carry);
+ z[1] = word_add(x[1], y[1], &carry);
+ z[2] = word_add(x[2], y[2], &carry);
+ z[3] = word_add(x[3], y[3], &carry);
+ z[4] = word_add(x[4], y[4], &carry);
+ z[5] = word_add(x[5], y[5], &carry);
+ z[6] = word_add(x[6], y[6], &carry);
+ z[7] = word_add(x[7], y[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+
+#else
+ word t0 = x - y;
+ word c1 = (t0 > x);
+ word z = t0 - *carry;
+ *carry = c1 | (z > t0);
+ return z;
+#endif
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#else
+ x[0] = word_sub(x[0], y[0], &carry);
+ x[1] = word_sub(x[1], y[1], &carry);
+ x[2] = word_sub(x[2], y[2], &carry);
+ x[3] = word_sub(x[3], y[3], &carry);
+ x[4] = word_sub(x[4], y[4], &carry);
+ x[5] = word_sub(x[5], y[5], &carry);
+ x[6] = word_sub(x[6], y[6], &carry);
+ x[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2_rev(word x[8], const word y[8], word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(y), [y]"r"(x), [z]"r"(x), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(y), [y]"r"(x), [z]"r"(x), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#else
+ x[0] = word_sub(y[0], x[0], &carry);
+ x[1] = word_sub(y[1], x[1], &carry);
+ x[2] = word_sub(y[2], x[2], &carry);
+ x[3] = word_sub(y[3], x[3], &carry);
+ x[4] = word_sub(y[4], x[4], &carry);
+ x[5] = word_sub(y[5], x[5], &carry);
+ x[6] = word_sub(y[6], x[6], &carry);
+ x[7] = word_sub(y[7], x[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+
+#else
+ z[0] = word_sub(x[0], y[0], &carry);
+ z[1] = word_sub(x[1], y[1], &carry);
+ z[2] = word_sub(x[2], y[2], &carry);
+ z[3] = word_sub(x[3], y[3], &carry);
+ z[4] = word_sub(x[4], y[4], &carry);
+ z[5] = word_sub(x[5], y[5], &carry);
+ z[6] = word_sub(x[6], y[6], &carry);
+ z[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+
+#else
+ x[0] = word_madd2(x[0], y, &carry);
+ x[1] = word_madd2(x[1], y, &carry);
+ x[2] = word_madd2(x[2], y, &carry);
+ x[3] = word_madd2(x[3], y, &carry);
+ x[4] = word_madd2(x[4], y, &carry);
+ x[5] = word_madd2(x[5], y, &carry);
+ x[6] = word_madd2(x[6], y, &carry);
+ x[7] = word_madd2(x[7], y, &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+
+#else
+ z[0] = word_madd2(x[0], y, &carry);
+ z[1] = word_madd2(x[1], y, &carry);
+ z[2] = word_madd2(x[2], y, &carry);
+ z[3] = word_madd2(x[3], y, &carry);
+ z[4] = word_madd2(x[4], y, &carry);
+ z[5] = word_madd2(x[5], y, &carry);
+ z[6] = word_madd2(x[6], y, &carry);
+ z[7] = word_madd2(x[7], y, &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+
+#else
+ z[0] = word_madd3(x[0], y, z[0], &carry);
+ z[1] = word_madd3(x[1], y, z[1], &carry);
+ z[2] = word_madd3(x[2], y, z[2], &carry);
+ z[3] = word_madd3(x[3], y, z[3], &carry);
+ z[4] = word_madd3(x[4], y, z[4], &carry);
+ z[5] = word_madd3(x[5], y, z[5], &carry);
+ z[6] = word_madd3(x[6], y, z[6], &carry);
+ z[7] = word_madd3(x[7], y, z[7], &carry);
+ return carry;
+#endif
+ }
+
+/*
+* Multiply-Add Accumulator
+* (w2,w1,w0) += x * y
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word x, word y)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ word z0 = 0, z1 = 0;
+
+ asm("mull %[y]"
+ : "=a"(z0),"=d"(z1)
+ : "a"(x), [y]"rm"(y)
+ : "cc");
+
+ asm(R"(
+ addl %[z0],%[w0]
+ adcl %[z1],%[w1]
+ adcl $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [z0]"r"(z0), [z1]"r"(z1), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ word z0 = 0, z1 = 0;
+
+ asm("mulq %[y]"
+ : "=a"(z0),"=d"(z1)
+ : "a"(x), [y]"rm"(y)
+ : "cc");
+
+ asm(R"(
+ addq %[z0],%[w0]
+ adcq %[z1],%[w1]
+ adcq $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [z0]"r"(z0), [z1]"r"(z1), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#else
+ word carry = *w0;
+ *w0 = word_madd2(x, y, &carry);
+ *w1 += carry;
+ *w2 += (*w1 < carry);
+#endif
+ }
+
+/*
+* 3-word addition
+* (w2,w1,w0) += x
+*/
+inline void word3_add(word* w2, word* w1, word* w0, word x)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(R"(
+ addl %[x],%[w0]
+ adcl $0,%[w1]
+ adcl $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"r"(x), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ asm(R"(
+ addq %[x],%[w0]
+ adcq $0,%[w1]
+ adcq $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"r"(x), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#else
+ *w0 += x;
+ word c1 = (*w0 < x);
+ *w1 += c1;
+ word c2 = (*w1 < c1);
+ *w2 += c2;
+#endif
+ }
+
+/*
+* Multiply-Add Accumulator
+* (w2,w1,w0) += 2 * x * y
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word x, word y)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+
+ word z0 = 0, z1 = 0;
+
+ asm("mull %[y]"
+ : "=a"(z0),"=d"(z1)
+ : "a"(x), [y]"rm"(y)
+ : "cc");
+
+ asm(R"(
+ addl %[z0],%[w0]
+ adcl %[z1],%[w1]
+ adcl $0,%[w2]
+
+ addl %[z0],%[w0]
+ adcl %[z1],%[w1]
+ adcl $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [z0]"r"(z0), [z1]"r"(z1), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+
+ word z0 = 0, z1 = 0;
+
+ asm("mulq %[y]"
+ : "=a"(z0),"=d"(z1)
+ : "a"(x), [y]"rm"(y)
+ : "cc");
+
+ asm(R"(
+ addq %[z0],%[w0]
+ adcq %[z1],%[w1]
+ adcq $0,%[w2]
+
+ addq %[z0],%[w0]
+ adcq %[z1],%[w1]
+ adcq $0,%[w2]
+ )"
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [z0]"r"(z0), [z1]"r"(z1), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+
+#else
+ word carry = 0;
+ x = word_madd2(x, y, &carry);
+ y = carry;
+
+ word top = (y >> (BOTAN_MP_WORD_BITS-1));
+ y <<= 1;
+ y |= (x >> (BOTAN_MP_WORD_BITS-1));
+ x <<= 1;
+
+ carry = 0;
+ *w0 = word_add(*w0, x, &carry);
+ *w1 = word_add(*w1, y, &carry);
+ *w2 = word_add(*w2, top, &carry);
+#endif
+ }
+
+#if defined(ASM)
+ #undef ASM
+ #undef DO_8_TIMES
+ #undef ADD_OR_SUBTRACT
+ #undef ADDSUB2_OP
+ #undef ADDSUB3_OP
+ #undef LINMUL_OP
+ #undef MULADD_OP
+#endif
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_comba.cpp b/comm/third_party/botan/src/lib/math/mp/mp_comba.cpp
new file mode 100644
index 0000000000..ec527224c8
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_comba.cpp
@@ -0,0 +1,2211 @@
+/*
+* Comba Multiplication and Squaring
+*
+* This file was automatically generated by ./src/scripts/comba.py on 2018-05-08
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_asmi.h>
+
+namespace Botan {
+
+/*
+* Comba 4x4 Squaring
+*/
+void bigint_comba_sqr4(word z[8], const word x[4])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0;
+ z[ 7] = w1;
+ }
+
+/*
+* Comba 4x4 Multiplication
+*/
+void bigint_comba_mul4(word z[8], const word x[4], const word y[4])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ z[ 6] = w0;
+ z[ 7] = w1;
+ }
+
+/*
+* Comba 6x6 Squaring
+*/
+void bigint_comba_sqr6(word z[12], const word x[6])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
+ word3_muladd (&w1, &w0, &w2, x[ 4], x[ 4]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd (&w0, &w2, &w1, x[ 5], x[ 5]);
+ z[10] = w1;
+ z[11] = w2;
+ }
+
+/*
+* Comba 6x6 Multiplication
+*/
+void bigint_comba_mul6(word z[12], const word x[6], const word y[6])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
+ z[10] = w1;
+ z[11] = w2;
+ }
+
+/*
+* Comba 8x8 Squaring
+*/
+void bigint_comba_sqr8(word z[16], const word x[8])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
+ word3_muladd (&w1, &w0, &w2, x[ 4], x[ 4]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
+ word3_muladd (&w0, &w2, &w1, x[ 5], x[ 5]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
+ word3_muladd (&w2, &w1, &w0, x[ 6], x[ 6]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd (&w1, &w0, &w2, x[ 7], x[ 7]);
+ z[14] = w2;
+ z[15] = w0;
+ }
+
+/*
+* Comba 8x8 Multiplication
+*/
+void bigint_comba_mul8(word z[16], const word x[8], const word y[8])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
+ z[14] = w2;
+ z[15] = w0;
+ }
+
+/*
+* Comba 9x9 Squaring
+*/
+void bigint_comba_sqr9(word z[18], const word x[9])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
+ word3_muladd (&w1, &w0, &w2, x[ 4], x[ 4]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
+ word3_muladd (&w0, &w2, &w1, x[ 5], x[ 5]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
+ word3_muladd (&w2, &w1, &w0, x[ 6], x[ 6]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[ 8]);
+ word3_muladd (&w1, &w0, &w2, x[ 7], x[ 7]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 8]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd (&w0, &w2, &w1, x[ 8], x[ 8]);
+ z[16] = w1;
+ z[17] = w2;
+ }
+
+/*
+* Comba 9x9 Multiplication
+*/
+void bigint_comba_mul9(word z[18], const word x[9], const word y[9])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 0]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 1]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 2]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 3]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 4]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 5]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 6]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 7]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 8]);
+ z[16] = w1;
+ z[17] = w2;
+ }
+
+/*
+* Comba 16x16 Squaring
+*/
+void bigint_comba_sqr16(word z[32], const word x[16])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
+ word3_muladd (&w1, &w0, &w2, x[ 4], x[ 4]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 9]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
+ word3_muladd (&w0, &w2, &w1, x[ 5], x[ 5]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 9]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
+ word3_muladd (&w2, &w1, &w0, x[ 6], x[ 6]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 9]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 9]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[ 8]);
+ word3_muladd (&w1, &w0, &w2, x[ 7], x[ 7]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 8]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[ 9]);
+ word3_muladd (&w0, &w2, &w1, x[ 8], x[ 8]);
+ z[16] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[ 9]);
+ z[17] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[10]);
+ word3_muladd (&w2, &w1, &w0, x[ 9], x[ 9]);
+ z[18] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[10]);
+ z[19] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[11]);
+ word3_muladd (&w1, &w0, &w2, x[10], x[10]);
+ z[20] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[11]);
+ z[21] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[12]);
+ word3_muladd (&w0, &w2, &w1, x[11], x[11]);
+ z[22] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[10], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[12]);
+ z[23] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[13]);
+ word3_muladd (&w2, &w1, &w0, x[12], x[12]);
+ z[24] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[11], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[12], x[13]);
+ z[25] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[12], x[14]);
+ word3_muladd (&w1, &w0, &w2, x[13], x[13]);
+ z[26] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[14]);
+ z[27] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[13], x[15]);
+ word3_muladd (&w0, &w2, &w1, x[14], x[14]);
+ z[28] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[14], x[15]);
+ z[29] = w2; w2 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[15], x[15]);
+ z[30] = w0;
+ z[31] = w1;
+ }
+
+/*
+* Comba 16x16 Multiplication
+*/
+void bigint_comba_mul16(word z[32], const word x[16], const word y[16])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 0]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 0]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 0]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 0]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 0]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 0]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 0]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 0]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 1]);
+ z[16] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 2]);
+ z[17] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 3]);
+ z[18] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 4]);
+ z[19] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 5]);
+ z[20] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 6]);
+ z[21] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 7]);
+ z[22] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 8]);
+ z[23] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 9]);
+ z[24] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[10], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[10]);
+ z[25] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[11], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[11]);
+ z[26] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[12], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[12]);
+ z[27] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[13], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[13]);
+ z[28] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[14], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[14]);
+ z[29] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[15], y[15]);
+ z[30] = w0;
+ z[31] = w1;
+ }
+
+/*
+* Comba 24x24 Squaring
+*/
+void bigint_comba_sqr24(word z[48], const word x[24])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd (&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
+ word3_muladd (&w1, &w0, &w2, x[ 1], x[ 1]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
+ word3_muladd (&w0, &w2, &w1, x[ 2], x[ 2]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd (&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
+ word3_muladd (&w1, &w0, &w2, x[ 4], x[ 4]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 9]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
+ word3_muladd (&w0, &w2, &w1, x[ 5], x[ 5]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 9]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 8]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
+ word3_muladd (&w2, &w1, &w0, x[ 6], x[ 6]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 9]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[ 8]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 9]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[ 8]);
+ word3_muladd (&w1, &w0, &w2, x[ 7], x[ 7]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 8]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[16]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[10]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[ 9]);
+ word3_muladd (&w0, &w2, &w1, x[ 8], x[ 8]);
+ z[16] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[17]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[16]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[11]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[10]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[ 9]);
+ z[17] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[17]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[16]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[10]);
+ word3_muladd (&w2, &w1, &w0, x[ 9], x[ 9]);
+ z[18] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[18]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[17]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[16]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[12]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[11]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[10]);
+ z[19] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[18]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[17]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[16]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[12]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[11]);
+ word3_muladd (&w1, &w0, &w2, x[10], x[10]);
+ z[20] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[19]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[17]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[16]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[11]);
+ z[21] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 0], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 1], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[18]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[17]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[16]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[13]);
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[12]);
+ word3_muladd (&w0, &w2, &w1, x[11], x[11]);
+ z[22] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 0], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 1], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 2], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[18]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[17]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[16]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[14]);
+ word3_muladd_2(&w1, &w0, &w2, x[10], x[13]);
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[12]);
+ z[23] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[19]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[17]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[16]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[13]);
+ word3_muladd (&w2, &w1, &w0, x[12], x[12]);
+ z[24] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 2], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 3], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 4], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[18]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[17]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[16]);
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[15]);
+ word3_muladd_2(&w0, &w2, &w1, x[11], x[14]);
+ word3_muladd_2(&w0, &w2, &w1, x[12], x[13]);
+ z[25] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 3], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 4], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 5], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[18]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[17]);
+ word3_muladd_2(&w1, &w0, &w2, x[10], x[16]);
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[15]);
+ word3_muladd_2(&w1, &w0, &w2, x[12], x[14]);
+ word3_muladd (&w1, &w0, &w2, x[13], x[13]);
+ z[26] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[19]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[17]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[16]);
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[14]);
+ z[27] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 5], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 6], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 7], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[18]);
+ word3_muladd_2(&w0, &w2, &w1, x[11], x[17]);
+ word3_muladd_2(&w0, &w2, &w1, x[12], x[16]);
+ word3_muladd_2(&w0, &w2, &w1, x[13], x[15]);
+ word3_muladd (&w0, &w2, &w1, x[14], x[14]);
+ z[28] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 6], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 7], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 8], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[10], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[18]);
+ word3_muladd_2(&w1, &w0, &w2, x[12], x[17]);
+ word3_muladd_2(&w1, &w0, &w2, x[13], x[16]);
+ word3_muladd_2(&w1, &w0, &w2, x[14], x[15]);
+ z[29] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[19]);
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[17]);
+ word3_muladd_2(&w2, &w1, &w0, x[14], x[16]);
+ word3_muladd (&w2, &w1, &w0, x[15], x[15]);
+ z[30] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[ 8], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[ 9], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[10], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[11], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[12], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[13], x[18]);
+ word3_muladd_2(&w0, &w2, &w1, x[14], x[17]);
+ word3_muladd_2(&w0, &w2, &w1, x[15], x[16]);
+ z[31] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[ 9], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[10], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[11], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[12], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[13], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[14], x[18]);
+ word3_muladd_2(&w1, &w0, &w2, x[15], x[17]);
+ word3_muladd (&w1, &w0, &w2, x[16], x[16]);
+ z[32] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[14], x[19]);
+ word3_muladd_2(&w2, &w1, &w0, x[15], x[18]);
+ word3_muladd_2(&w2, &w1, &w0, x[16], x[17]);
+ z[33] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[11], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[12], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[13], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[14], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[15], x[19]);
+ word3_muladd_2(&w0, &w2, &w1, x[16], x[18]);
+ word3_muladd (&w0, &w2, &w1, x[17], x[17]);
+ z[34] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[12], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[13], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[14], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[15], x[20]);
+ word3_muladd_2(&w1, &w0, &w2, x[16], x[19]);
+ word3_muladd_2(&w1, &w0, &w2, x[17], x[18]);
+ z[35] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[14], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[15], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[16], x[20]);
+ word3_muladd_2(&w2, &w1, &w0, x[17], x[19]);
+ word3_muladd (&w2, &w1, &w0, x[18], x[18]);
+ z[36] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[14], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[15], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[16], x[21]);
+ word3_muladd_2(&w0, &w2, &w1, x[17], x[20]);
+ word3_muladd_2(&w0, &w2, &w1, x[18], x[19]);
+ z[37] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[15], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[16], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[17], x[21]);
+ word3_muladd_2(&w1, &w0, &w2, x[18], x[20]);
+ word3_muladd (&w1, &w0, &w2, x[19], x[19]);
+ z[38] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[16], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[17], x[22]);
+ word3_muladd_2(&w2, &w1, &w0, x[18], x[21]);
+ word3_muladd_2(&w2, &w1, &w0, x[19], x[20]);
+ z[39] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[17], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[18], x[22]);
+ word3_muladd_2(&w0, &w2, &w1, x[19], x[21]);
+ word3_muladd (&w0, &w2, &w1, x[20], x[20]);
+ z[40] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[18], x[23]);
+ word3_muladd_2(&w1, &w0, &w2, x[19], x[22]);
+ word3_muladd_2(&w1, &w0, &w2, x[20], x[21]);
+ z[41] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[19], x[23]);
+ word3_muladd_2(&w2, &w1, &w0, x[20], x[22]);
+ word3_muladd (&w2, &w1, &w0, x[21], x[21]);
+ z[42] = w0; w0 = 0;
+
+ word3_muladd_2(&w0, &w2, &w1, x[20], x[23]);
+ word3_muladd_2(&w0, &w2, &w1, x[21], x[22]);
+ z[43] = w1; w1 = 0;
+
+ word3_muladd_2(&w1, &w0, &w2, x[21], x[23]);
+ word3_muladd (&w1, &w0, &w2, x[22], x[22]);
+ z[44] = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[22], x[23]);
+ z[45] = w0; w0 = 0;
+
+ word3_muladd (&w0, &w2, &w1, x[23], x[23]);
+ z[46] = w1;
+ z[47] = w2;
+ }
+
+/*
+* Comba 24x24 Multiplication
+*/
+void bigint_comba_mul24(word z[48], const word x[24], const word y[24])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[ 0] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
+ z[ 1] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
+ z[ 2] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[ 3] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
+ z[ 4] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
+ z[ 5] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
+ z[ 6] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
+ z[ 7] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 0]);
+ z[ 8] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 0]);
+ z[ 9] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 0]);
+ z[10] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 0]);
+ z[11] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 0]);
+ z[12] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 0]);
+ z[13] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 0]);
+ z[14] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 0]);
+ z[15] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[ 0]);
+ z[16] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[ 0]);
+ z[17] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[ 0]);
+ z[18] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[ 0]);
+ z[19] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[ 0]);
+ z[20] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[ 0]);
+ z[21] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 0], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[ 1], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[ 2]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[ 1]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[ 0]);
+ z[22] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 0], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[ 1], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[ 2], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[ 3]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[ 2]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[ 1]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[ 0]);
+ z[23] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[ 1]);
+ z[24] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 2], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[ 3], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[ 4], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[ 5]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[ 4]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[ 3]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[ 2]);
+ z[25] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 3], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[ 4], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[ 5], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[ 6]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[ 5]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[ 4]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[ 3]);
+ z[26] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[ 4]);
+ z[27] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 5], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[ 6], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[ 7], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[ 8]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[ 7]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[ 6]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[ 5]);
+ z[28] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 6], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[ 7], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[ 8], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[ 9]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[ 8]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[ 7]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[ 6]);
+ z[29] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[ 7]);
+ z[30] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[ 8], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[ 9], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[10], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[11], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[11]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[10]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[ 9]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[ 8]);
+ z[31] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[ 9], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[10], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[11], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[12], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[12]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[11]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[10]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[ 9]);
+ z[32] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[10], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[10]);
+ z[33] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[11], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[12], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[13], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[14], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[14]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[13]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[12]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[11]);
+ z[34] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[12], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[13], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[14], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[15], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[15]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[14]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[13]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[12]);
+ z[35] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[13], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[16], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[16]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[13]);
+ z[36] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[14], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[15], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[16], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[17], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[17]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[16]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[15]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[14]);
+ z[37] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[15], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[16], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[17], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[18], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[18]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[17]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[16]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[15]);
+ z[38] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[16], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[17], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[18], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[19], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[19]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[18]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[17]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[16]);
+ z[39] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[17], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[18], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[19], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[20], y[20]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[19]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[18]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[17]);
+ z[40] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[18], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[19], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[20], y[21]);
+ word3_muladd(&w1, &w0, &w2, x[21], y[20]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[19]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[18]);
+ z[41] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[19], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[20], y[22]);
+ word3_muladd(&w2, &w1, &w0, x[21], y[21]);
+ word3_muladd(&w2, &w1, &w0, x[22], y[20]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[19]);
+ z[42] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[20], y[23]);
+ word3_muladd(&w0, &w2, &w1, x[21], y[22]);
+ word3_muladd(&w0, &w2, &w1, x[22], y[21]);
+ word3_muladd(&w0, &w2, &w1, x[23], y[20]);
+ z[43] = w1; w1 = 0;
+
+ word3_muladd(&w1, &w0, &w2, x[21], y[23]);
+ word3_muladd(&w1, &w0, &w2, x[22], y[22]);
+ word3_muladd(&w1, &w0, &w2, x[23], y[21]);
+ z[44] = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[22], y[23]);
+ word3_muladd(&w2, &w1, &w0, x[23], y[22]);
+ z[45] = w0; w0 = 0;
+
+ word3_muladd(&w0, &w2, &w1, x[23], y[23]);
+ z[46] = w1;
+ z[47] = w2;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_core.h b/comm/third_party/botan/src/lib/math/mp/mp_core.h
new file mode 100644
index 0000000000..c4bf8e8815
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_core.h
@@ -0,0 +1,819 @@
+/*
+* MPI Algorithms
+* (C) 1999-2010,2018 Jack Lloyd
+* 2006 Luca Piccarreta
+* 2016 Matthias Gierlings
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MP_CORE_OPS_H_
+#define BOTAN_MP_CORE_OPS_H_
+
+#include <botan/types.h>
+#include <botan/exceptn.h>
+#include <botan/mem_ops.h>
+#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
+#include <algorithm>
+
+namespace Botan {
+
+const word MP_WORD_MAX = ~static_cast<word>(0);
+
+/*
+* If cond == 0, does nothing.
+* If cond > 0, swaps x[0:size] with y[0:size]
+* Runs in constant time
+*/
+inline void bigint_cnd_swap(word cnd, word x[], word y[], size_t size)
+ {
+ const auto mask = CT::Mask<word>::expand(cnd);
+
+ for(size_t i = 0; i != size; ++i)
+ {
+ const word a = x[i];
+ const word b = y[i];
+ x[i] = mask.select(b, a);
+ y[i] = mask.select(a, b);
+ }
+ }
+
+inline word bigint_cnd_add(word cnd, word x[], word x_size,
+ const word y[], size_t y_size)
+ {
+ BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
+
+ const auto mask = CT::Mask<word>::expand(cnd);
+
+ word carry = 0;
+
+ const size_t blocks = y_size - (y_size % 8);
+ word z[8] = { 0 };
+
+ for(size_t i = 0; i != blocks; i += 8)
+ {
+ carry = word8_add3(z, x + i, y + i, carry);
+ mask.select_n(x + i, z, x + i, 8);
+ }
+
+ for(size_t i = blocks; i != y_size; ++i)
+ {
+ z[0] = word_add(x[i], y[i], &carry);
+ x[i] = mask.select(z[0], x[i]);
+ }
+
+ for(size_t i = y_size; i != x_size; ++i)
+ {
+ z[0] = word_add(x[i], 0, &carry);
+ x[i] = mask.select(z[0], x[i]);
+ }
+
+ return mask.if_set_return(carry);
+ }
+
+/*
+* If cond > 0 adds x[0:size] and y[0:size] and returns carry
+* Runs in constant time
+*/
+inline word bigint_cnd_add(word cnd, word x[], const word y[], size_t size)
+ {
+ return bigint_cnd_add(cnd, x, size, y, size);
+ }
+
+/*
+* If cond > 0 subtracts x[0:size] and y[0:size] and returns borrow
+* Runs in constant time
+*/
+inline word bigint_cnd_sub(word cnd,
+ word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
+
+ const auto mask = CT::Mask<word>::expand(cnd);
+
+ word carry = 0;
+
+ const size_t blocks = y_size - (y_size % 8);
+ word z[8] = { 0 };
+
+ for(size_t i = 0; i != blocks; i += 8)
+ {
+ carry = word8_sub3(z, x + i, y + i, carry);
+ mask.select_n(x + i, z, x + i, 8);
+ }
+
+ for(size_t i = blocks; i != y_size; ++i)
+ {
+ z[0] = word_sub(x[i], y[i], &carry);
+ x[i] = mask.select(z[0], x[i]);
+ }
+
+ for(size_t i = y_size; i != x_size; ++i)
+ {
+ z[0] = word_sub(x[i], 0, &carry);
+ x[i] = mask.select(z[0], x[i]);
+ }
+
+ return mask.if_set_return(carry);
+ }
+
+/*
+* If cond > 0 adds x[0:size] and y[0:size] and returns carry
+* Runs in constant time
+*/
+inline word bigint_cnd_sub(word cnd, word x[], const word y[], size_t size)
+ {
+ return bigint_cnd_sub(cnd, x, size, y, size);
+ }
+
+
+/*
+* Equivalent to
+* bigint_cnd_add( mask, x, y, size);
+* bigint_cnd_sub(~mask, x, y, size);
+*
+* Mask must be either 0 or all 1 bits
+*/
+inline void bigint_cnd_add_or_sub(CT::Mask<word> mask, word x[], const word y[], size_t size)
+ {
+ const size_t blocks = size - (size % 8);
+
+ word carry = 0;
+ word borrow = 0;
+
+ word t0[8] = { 0 };
+ word t1[8] = { 0 };
+
+ for(size_t i = 0; i != blocks; i += 8)
+ {
+ carry = word8_add3(t0, x + i, y + i, carry);
+ borrow = word8_sub3(t1, x + i, y + i, borrow);
+
+ for(size_t j = 0; j != 8; ++j)
+ x[i+j] = mask.select(t0[j], t1[j]);
+ }
+
+ for(size_t i = blocks; i != size; ++i)
+ {
+ const word a = word_add(x[i], y[i], &carry);
+ const word s = word_sub(x[i], y[i], &borrow);
+
+ x[i] = mask.select(a, s);
+ }
+ }
+
+/*
+* Equivalent to
+* bigint_cnd_add( mask, x, size, y, size);
+* bigint_cnd_sub(~mask, x, size, z, size);
+*
+* Mask must be either 0 or all 1 bits
+*
+* Returns the carry or borrow resp
+*/
+inline word bigint_cnd_addsub(CT::Mask<word> mask, word x[],
+ const word y[], const word z[],
+ size_t size)
+ {
+ const size_t blocks = size - (size % 8);
+
+ word carry = 0;
+ word borrow = 0;
+
+ word t0[8] = { 0 };
+ word t1[8] = { 0 };
+
+ for(size_t i = 0; i != blocks; i += 8)
+ {
+ carry = word8_add3(t0, x + i, y + i, carry);
+ borrow = word8_sub3(t1, x + i, z + i, borrow);
+
+ for(size_t j = 0; j != 8; ++j)
+ x[i+j] = mask.select(t0[j], t1[j]);
+ }
+
+ for(size_t i = blocks; i != size; ++i)
+ {
+ t0[0] = word_add(x[i], y[i], &carry);
+ t1[0] = word_sub(x[i], z[i], &borrow);
+ x[i] = mask.select(t0[0], t1[0]);
+ }
+
+ return mask.select(carry, borrow);
+ }
+
+/*
+* 2s complement absolute value
+* If cond > 0 sets x to ~x + 1
+* Runs in constant time
+*/
+inline void bigint_cnd_abs(word cnd, word x[], size_t size)
+ {
+ const auto mask = CT::Mask<word>::expand(cnd);
+
+ word carry = mask.if_set_return(1);
+ for(size_t i = 0; i != size; ++i)
+ {
+ const word z = word_add(~x[i], 0, &carry);
+ x[i] = mask.select(z, x[i]);
+ }
+ }
+
+/**
+* Two operand addition with carry out
+*/
+inline word bigint_add2_nc(word x[], size_t x_size, const word y[], size_t y_size)
+ {
+ word carry = 0;
+
+ BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
+
+ const size_t blocks = y_size - (y_size % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ carry = word8_add2(x + i, y + i, carry);
+
+ for(size_t i = blocks; i != y_size; ++i)
+ x[i] = word_add(x[i], y[i], &carry);
+
+ for(size_t i = y_size; i != x_size; ++i)
+ x[i] = word_add(x[i], 0, &carry);
+
+ return carry;
+ }
+
+/**
+* Three operand addition with carry out
+*/
+inline word bigint_add3_nc(word z[],
+ const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ if(x_size < y_size)
+ { return bigint_add3_nc(z, y, y_size, x, x_size); }
+
+ word carry = 0;
+
+ const size_t blocks = y_size - (y_size % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ carry = word8_add3(z + i, x + i, y + i, carry);
+
+ for(size_t i = blocks; i != y_size; ++i)
+ z[i] = word_add(x[i], y[i], &carry);
+
+ for(size_t i = y_size; i != x_size; ++i)
+ z[i] = word_add(x[i], 0, &carry);
+
+ return carry;
+ }
+
+/**
+* Two operand addition
+* @param x the first operand (and output)
+* @param x_size size of x
+* @param y the second operand
+* @param y_size size of y (must be >= x_size)
+*/
+inline void bigint_add2(word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ x[x_size] += bigint_add2_nc(x, x_size, y, y_size);
+ }
+
+/**
+* Three operand addition
+*/
+inline void bigint_add3(word z[],
+ const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ z[x_size > y_size ? x_size : y_size] +=
+ bigint_add3_nc(z, x, x_size, y, y_size);
+ }
+
+/**
+* Two operand subtraction
+*/
+inline word bigint_sub2(word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ word borrow = 0;
+
+ BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
+
+ const size_t blocks = y_size - (y_size % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ borrow = word8_sub2(x + i, y + i, borrow);
+
+ for(size_t i = blocks; i != y_size; ++i)
+ x[i] = word_sub(x[i], y[i], &borrow);
+
+ for(size_t i = y_size; i != x_size; ++i)
+ x[i] = word_sub(x[i], 0, &borrow);
+
+ return borrow;
+ }
+
+/**
+* Two operand subtraction, x = y - x; assumes y >= x
+*/
+inline void bigint_sub2_rev(word x[], const word y[], size_t y_size)
+ {
+ word borrow = 0;
+
+ const size_t blocks = y_size - (y_size % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ borrow = word8_sub2_rev(x + i, y + i, borrow);
+
+ for(size_t i = blocks; i != y_size; ++i)
+ x[i] = word_sub(y[i], x[i], &borrow);
+
+ BOTAN_ASSERT(borrow == 0, "y must be greater than x");
+ }
+
+/**
+* Three operand subtraction
+*/
+inline word bigint_sub3(word z[],
+ const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ word borrow = 0;
+
+ BOTAN_ASSERT(x_size >= y_size, "Expected sizes");
+
+ const size_t blocks = y_size - (y_size % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ borrow = word8_sub3(z + i, x + i, y + i, borrow);
+
+ for(size_t i = blocks; i != y_size; ++i)
+ z[i] = word_sub(x[i], y[i], &borrow);
+
+ for(size_t i = y_size; i != x_size; ++i)
+ z[i] = word_sub(x[i], 0, &borrow);
+
+ return borrow;
+ }
+
+/**
+* Return abs(x-y), ie if x >= y, then compute z = x - y
+* Otherwise compute z = y - x
+* No borrow is possible since the result is always >= 0
+*
+* Returns ~0 if x >= y or 0 if x < y
+* @param z output array of at least N words
+* @param x input array of N words
+* @param y input array of N words
+* @param N length of x and y
+* @param ws array of at least 2*N words
+*/
+inline CT::Mask<word>
+bigint_sub_abs(word z[],
+ const word x[], const word y[], size_t N,
+ word ws[])
+ {
+ // Subtract in both direction then conditional copy out the result
+
+ word* ws0 = ws;
+ word* ws1 = ws + N;
+
+ word borrow0 = 0;
+ word borrow1 = 0;
+
+ const size_t blocks = N - (N % 8);
+
+ for(size_t i = 0; i != blocks; i += 8)
+ {
+ borrow0 = word8_sub3(ws0 + i, x + i, y + i, borrow0);
+ borrow1 = word8_sub3(ws1 + i, y + i, x + i, borrow1);
+ }
+
+ for(size_t i = blocks; i != N; ++i)
+ {
+ ws0[i] = word_sub(x[i], y[i], &borrow0);
+ ws1[i] = word_sub(y[i], x[i], &borrow1);
+ }
+
+ return CT::conditional_copy_mem(borrow0, z, ws1, ws0, N);
+ }
+
+/*
+* Shift Operations
+*/
+inline void bigint_shl1(word x[], size_t x_size, size_t x_words,
+ size_t word_shift, size_t bit_shift)
+ {
+ copy_mem(x + word_shift, x, x_words);
+ clear_mem(x, word_shift);
+
+ const auto carry_mask = CT::Mask<word>::expand(bit_shift);
+ const size_t carry_shift = carry_mask.if_set_return(BOTAN_MP_WORD_BITS - bit_shift);
+
+ word carry = 0;
+ for(size_t i = word_shift; i != x_size; ++i)
+ {
+ const word w = x[i];
+ x[i] = (w << bit_shift) | carry;
+ carry = carry_mask.if_set_return(w >> carry_shift);
+ }
+ }
+
+inline void bigint_shr1(word x[], size_t x_size,
+ size_t word_shift, size_t bit_shift)
+ {
+ const size_t top = x_size >= word_shift ? (x_size - word_shift) : 0;
+
+ if(top > 0)
+ copy_mem(x, x + word_shift, top);
+ clear_mem(x + top, std::min(word_shift, x_size));
+
+ const auto carry_mask = CT::Mask<word>::expand(bit_shift);
+ const size_t carry_shift = carry_mask.if_set_return(BOTAN_MP_WORD_BITS - bit_shift);
+
+ word carry = 0;
+
+ for(size_t i = 0; i != top; ++i)
+ {
+ const word w = x[top - i - 1];
+ x[top-i-1] = (w >> bit_shift) | carry;
+ carry = carry_mask.if_set_return(w << carry_shift);
+ }
+ }
+
+inline void bigint_shl2(word y[], const word x[], size_t x_size,
+ size_t word_shift, size_t bit_shift)
+ {
+ copy_mem(y + word_shift, x, x_size);
+
+ const auto carry_mask = CT::Mask<word>::expand(bit_shift);
+ const size_t carry_shift = carry_mask.if_set_return(BOTAN_MP_WORD_BITS - bit_shift);
+
+ word carry = 0;
+ for(size_t i = word_shift; i != x_size + word_shift + 1; ++i)
+ {
+ const word w = y[i];
+ y[i] = (w << bit_shift) | carry;
+ carry = carry_mask.if_set_return(w >> carry_shift);
+ }
+ }
+
+inline void bigint_shr2(word y[], const word x[], size_t x_size,
+ size_t word_shift, size_t bit_shift)
+ {
+ const size_t new_size = x_size < word_shift ? 0 : (x_size - word_shift);
+
+ if(new_size > 0)
+ copy_mem(y, x + word_shift, new_size);
+
+ const auto carry_mask = CT::Mask<word>::expand(bit_shift);
+ const size_t carry_shift = carry_mask.if_set_return(BOTAN_MP_WORD_BITS - bit_shift);
+
+ word carry = 0;
+ for(size_t i = new_size; i > 0; --i)
+ {
+ word w = y[i-1];
+ y[i-1] = (w >> bit_shift) | carry;
+ carry = carry_mask.if_set_return(w << carry_shift);
+ }
+ }
+
+/*
+* Linear Multiply - returns the carry
+*/
+inline word BOTAN_WARN_UNUSED_RESULT bigint_linmul2(word x[], size_t x_size, word y)
+ {
+ const size_t blocks = x_size - (x_size % 8);
+
+ word carry = 0;
+
+ for(size_t i = 0; i != blocks; i += 8)
+ carry = word8_linmul2(x + i, y, carry);
+
+ for(size_t i = blocks; i != x_size; ++i)
+ x[i] = word_madd2(x[i], y, &carry);
+
+ return carry;
+ }
+
+inline void bigint_linmul3(word z[], const word x[], size_t x_size, word y)
+ {
+ const size_t blocks = x_size - (x_size % 8);
+
+ word carry = 0;
+
+ for(size_t i = 0; i != blocks; i += 8)
+ carry = word8_linmul3(z + i, x + i, y, carry);
+
+ for(size_t i = blocks; i != x_size; ++i)
+ z[i] = word_madd2(x[i], y, &carry);
+
+ z[x_size] = carry;
+ }
+
+/**
+* Compare x and y
+* Return -1 if x < y
+* Return 0 if x == y
+* Return 1 if x > y
+*/
+inline int32_t bigint_cmp(const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ static_assert(sizeof(word) >= sizeof(uint32_t), "Size assumption");
+
+ const word LT = static_cast<word>(-1);
+ const word EQ = 0;
+ const word GT = 1;
+
+ const size_t common_elems = std::min(x_size, y_size);
+
+ word result = EQ; // until found otherwise
+
+ for(size_t i = 0; i != common_elems; i++)
+ {
+ const auto is_eq = CT::Mask<word>::is_equal(x[i], y[i]);
+ const auto is_lt = CT::Mask<word>::is_lt(x[i], y[i]);
+
+ result = is_eq.select(result, is_lt.select(LT, GT));
+ }
+
+ if(x_size < y_size)
+ {
+ word mask = 0;
+ for(size_t i = x_size; i != y_size; i++)
+ mask |= y[i];
+
+ // If any bits were set in high part of y, then x < y
+ result = CT::Mask<word>::is_zero(mask).select(result, LT);
+ }
+ else if(y_size < x_size)
+ {
+ word mask = 0;
+ for(size_t i = y_size; i != x_size; i++)
+ mask |= x[i];
+
+ // If any bits were set in high part of x, then x > y
+ result = CT::Mask<word>::is_zero(mask).select(result, GT);
+ }
+
+ CT::unpoison(result);
+ BOTAN_DEBUG_ASSERT(result == LT || result == GT || result == EQ);
+ return static_cast<int32_t>(result);
+ }
+
+/**
+* Compare x and y
+* Return ~0 if x[0:x_size] < y[0:y_size] or 0 otherwise
+* If lt_or_equal is true, returns ~0 also for x == y
+*/
+inline CT::Mask<word>
+bigint_ct_is_lt(const word x[], size_t x_size,
+ const word y[], size_t y_size,
+ bool lt_or_equal = false)
+ {
+ const size_t common_elems = std::min(x_size, y_size);
+
+ auto is_lt = CT::Mask<word>::expand(lt_or_equal);
+
+ for(size_t i = 0; i != common_elems; i++)
+ {
+ const auto eq = CT::Mask<word>::is_equal(x[i], y[i]);
+ const auto lt = CT::Mask<word>::is_lt(x[i], y[i]);
+ is_lt = eq.select_mask(is_lt, lt);
+ }
+
+ if(x_size < y_size)
+ {
+ word mask = 0;
+ for(size_t i = x_size; i != y_size; i++)
+ mask |= y[i];
+ // If any bits were set in high part of y, then is_lt should be forced true
+ is_lt |= CT::Mask<word>::expand(mask);
+ }
+ else if(y_size < x_size)
+ {
+ word mask = 0;
+ for(size_t i = y_size; i != x_size; i++)
+ mask |= x[i];
+
+ // If any bits were set in high part of x, then is_lt should be false
+ is_lt &= CT::Mask<word>::is_zero(mask);
+ }
+
+ return is_lt;
+ }
+
+inline CT::Mask<word>
+bigint_ct_is_eq(const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ const size_t common_elems = std::min(x_size, y_size);
+
+ word diff = 0;
+
+ for(size_t i = 0; i != common_elems; i++)
+ {
+ diff |= (x[i] ^ y[i]);
+ }
+
+ // If any bits were set in high part of x/y, then they are not equal
+ if(x_size < y_size)
+ {
+ for(size_t i = x_size; i != y_size; i++)
+ diff |= y[i];
+ }
+ else if(y_size < x_size)
+ {
+ for(size_t i = y_size; i != x_size; i++)
+ diff |= x[i];
+ }
+
+ return CT::Mask<word>::is_zero(diff);
+ }
+
+/**
+* Set z to abs(x-y), ie if x >= y, then compute z = x - y
+* Otherwise compute z = y - x
+* No borrow is possible since the result is always >= 0
+*
+* Return the relative size of x vs y (-1, 0, 1)
+*
+* @param z output array of max(x_size,y_size) words
+* @param x input param
+* @param x_size length of x
+* @param y input param
+* @param y_size length of y
+*/
+inline int32_t
+bigint_sub_abs(word z[],
+ const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ const int32_t relative_size = bigint_cmp(x, x_size, y, y_size);
+
+ // Swap if relative_size == -1
+ const bool need_swap = relative_size < 0;
+ CT::conditional_swap_ptr(need_swap, x, y);
+ CT::conditional_swap(need_swap, x_size, y_size);
+
+ /*
+ * We know at this point that x >= y so if y_size is larger than
+ * x_size, we are guaranteed they are just leading zeros which can
+ * be ignored
+ */
+ y_size = std::min(x_size, y_size);
+
+ bigint_sub3(z, x, x_size, y, y_size);
+
+ return relative_size;
+ }
+
+/**
+* Set t to t-s modulo mod
+*
+* @param t first integer
+* @param s second integer
+* @param mod the modulus
+* @param mod_sw size of t, s, and mod
+* @param ws workspace of size mod_sw
+*/
+inline void
+bigint_mod_sub(word t[], const word s[], const word mod[], size_t mod_sw, word ws[])
+ {
+ // is t < s or not?
+ const auto is_lt = bigint_ct_is_lt(t, mod_sw, s, mod_sw);
+
+ // ws = p - s
+ const word borrow = bigint_sub3(ws, mod, mod_sw, s, mod_sw);
+
+ // Compute either (t - s) or (t + (p - s)) depending on mask
+ const word carry = bigint_cnd_addsub(is_lt, t, ws, s, mod_sw);
+
+ BOTAN_DEBUG_ASSERT(borrow == 0 && carry == 0);
+ BOTAN_UNUSED(carry, borrow);
+ }
+
+template<size_t N>
+inline void bigint_mod_sub_n(word t[], const word s[], const word mod[], word ws[])
+ {
+ // is t < s or not?
+ const auto is_lt = bigint_ct_is_lt(t, N, s, N);
+
+ // ws = p - s
+ const word borrow = bigint_sub3(ws, mod, N, s, N);
+
+ // Compute either (t - s) or (t + (p - s)) depending on mask
+ const word carry = bigint_cnd_addsub(is_lt, t, ws, s, N);
+
+ BOTAN_DEBUG_ASSERT(borrow == 0 && carry == 0);
+ BOTAN_UNUSED(carry, borrow);
+ }
+
+/**
+* Compute ((n1<<bits) + n0) / d
+*/
+inline word bigint_divop(word n1, word n0, word d)
+ {
+ if(d == 0)
+ throw Invalid_Argument("bigint_divop divide by zero");
+
+#if defined(BOTAN_HAS_MP_DWORD)
+ return ((static_cast<dword>(n1) << BOTAN_MP_WORD_BITS) | n0) / d;
+#else
+
+ word high = n1 % d;
+ word quotient = 0;
+
+ for(size_t i = 0; i != BOTAN_MP_WORD_BITS; ++i)
+ {
+ const word high_top_bit = high >> (BOTAN_MP_WORD_BITS-1);
+
+ high <<= 1;
+ high |= (n0 >> (BOTAN_MP_WORD_BITS-1-i)) & 1;
+ quotient <<= 1;
+
+ if(high_top_bit || high >= d)
+ {
+ high -= d;
+ quotient |= 1;
+ }
+ }
+
+ return quotient;
+#endif
+ }
+
+/**
+* Compute ((n1<<bits) + n0) % d
+*/
+inline word bigint_modop(word n1, word n0, word d)
+ {
+ if(d == 0)
+ throw Invalid_Argument("bigint_modop divide by zero");
+
+#if defined(BOTAN_HAS_MP_DWORD)
+ return ((static_cast<dword>(n1) << BOTAN_MP_WORD_BITS) | n0) % d;
+#else
+ word z = bigint_divop(n1, n0, d);
+ word dummy = 0;
+ z = word_madd2(z, d, &dummy);
+ return (n0-z);
+#endif
+ }
+
+/*
+* Comba Multiplication / Squaring
+*/
+void bigint_comba_mul4(word z[8], const word x[4], const word y[4]);
+void bigint_comba_mul6(word z[12], const word x[6], const word y[6]);
+void bigint_comba_mul8(word z[16], const word x[8], const word y[8]);
+void bigint_comba_mul9(word z[18], const word x[9], const word y[9]);
+void bigint_comba_mul16(word z[32], const word x[16], const word y[16]);
+void bigint_comba_mul24(word z[48], const word x[24], const word y[24]);
+
+void bigint_comba_sqr4(word out[8], const word in[4]);
+void bigint_comba_sqr6(word out[12], const word in[6]);
+void bigint_comba_sqr8(word out[16], const word in[8]);
+void bigint_comba_sqr9(word out[18], const word in[9]);
+void bigint_comba_sqr16(word out[32], const word in[16]);
+void bigint_comba_sqr24(word out[48], const word in[24]);
+
+/**
+* Montgomery Reduction
+* @param z integer to reduce, of size exactly 2*(p_size+1).
+ Output is in the first p_size+1 words, higher
+ words are set to zero.
+* @param p modulus
+* @param p_size size of p
+* @param p_dash Montgomery value
+* @param workspace array of at least 2*(p_size+1) words
+* @param ws_size size of workspace in words
+*/
+void bigint_monty_redc(word z[],
+ const word p[], size_t p_size,
+ word p_dash,
+ word workspace[],
+ size_t ws_size);
+
+/*
+* High Level Multiplication/Squaring Interfaces
+*/
+
+void bigint_mul(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word y[], size_t y_size, size_t y_sw,
+ word workspace[], size_t ws_size);
+
+void bigint_sqr(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ word workspace[], size_t ws_size);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_karat.cpp b/comm/third_party/botan/src/lib/math/mp/mp_karat.cpp
new file mode 100644
index 0000000000..15fcafa5be
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_karat.cpp
@@ -0,0 +1,408 @@
+/*
+* Multiplication and Squaring
+* (C) 1999-2010,2018 Jack Lloyd
+* 2016 Matthias Gierlings
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
+#include <botan/mem_ops.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+const size_t KARATSUBA_MULTIPLY_THRESHOLD = 32;
+const size_t KARATSUBA_SQUARE_THRESHOLD = 32;
+
+/*
+* Simple O(N^2) Multiplication
+*/
+void basecase_mul(word z[], size_t z_size,
+ const word x[], size_t x_size,
+ const word y[], size_t y_size)
+ {
+ if(z_size < x_size + y_size)
+ throw Invalid_Argument("basecase_mul z_size too small");
+
+ const size_t x_size_8 = x_size - (x_size % 8);
+
+ clear_mem(z, z_size);
+
+ for(size_t i = 0; i != y_size; ++i)
+ {
+ const word y_i = y[i];
+
+ word carry = 0;
+
+ for(size_t j = 0; j != x_size_8; j += 8)
+ carry = word8_madd3(z + i + j, x + j, y_i, carry);
+
+ for(size_t j = x_size_8; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], y_i, z[i+j], &carry);
+
+ z[x_size+i] = carry;
+ }
+ }
+
+void basecase_sqr(word z[], size_t z_size,
+ const word x[], size_t x_size)
+ {
+ if(z_size < 2*x_size)
+ throw Invalid_Argument("basecase_sqr z_size too small");
+
+ const size_t x_size_8 = x_size - (x_size % 8);
+
+ clear_mem(z, z_size);
+
+ for(size_t i = 0; i != x_size; ++i)
+ {
+ const word x_i = x[i];
+
+ word carry = 0;
+
+ for(size_t j = 0; j != x_size_8; j += 8)
+ carry = word8_madd3(z + i + j, x + j, x_i, carry);
+
+ for(size_t j = x_size_8; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], x_i, z[i+j], &carry);
+
+ z[x_size+i] = carry;
+ }
+ }
+
+/*
+* Karatsuba Multiplication Operation
+*/
+void karatsuba_mul(word z[], const word x[], const word y[], size_t N,
+ word workspace[])
+ {
+ if(N < KARATSUBA_MULTIPLY_THRESHOLD || N % 2)
+ {
+ switch(N)
+ {
+ case 6:
+ return bigint_comba_mul6(z, x, y);
+ case 8:
+ return bigint_comba_mul8(z, x, y);
+ case 9:
+ return bigint_comba_mul9(z, x, y);
+ case 16:
+ return bigint_comba_mul16(z, x, y);
+ case 24:
+ return bigint_comba_mul24(z, x, y);
+ default:
+ return basecase_mul(z, 2*N, x, N, y, N);
+ }
+ }
+
+ const size_t N2 = N / 2;
+
+ const word* x0 = x;
+ const word* x1 = x + N2;
+ const word* y0 = y;
+ const word* y1 = y + N2;
+ word* z0 = z;
+ word* z1 = z + N;
+
+ word* ws0 = workspace;
+ word* ws1 = workspace + N;
+
+ clear_mem(workspace, 2*N);
+
+ /*
+ * If either of cmp0 or cmp1 is zero then z0 or z1 resp is zero here,
+ * resulting in a no-op - z0*z1 will be equal to zero so we don't need to do
+ * anything, clear_mem above already set the correct result.
+ *
+ * However we ignore the result of the comparisons and always perform the
+ * subtractions and recursively multiply to avoid the timing channel.
+ */
+
+ // First compute (X_lo - X_hi)*(Y_hi - Y_lo)
+ const auto cmp0 = bigint_sub_abs(z0, x0, x1, N2, workspace);
+ const auto cmp1 = bigint_sub_abs(z1, y1, y0, N2, workspace);
+ const auto neg_mask = ~(cmp0 ^ cmp1);
+
+ karatsuba_mul(ws0, z0, z1, N2, ws1);
+
+ // Compute X_lo * Y_lo
+ karatsuba_mul(z0, x0, y0, N2, ws1);
+
+ // Compute X_hi * Y_hi
+ karatsuba_mul(z1, x1, y1, N2, ws1);
+
+ const word ws_carry = bigint_add3_nc(ws1, z0, N, z1, N);
+ word z_carry = bigint_add2_nc(z + N2, N, ws1, N);
+
+ z_carry += bigint_add2_nc(z + N + N2, N2, &ws_carry, 1);
+ bigint_add2_nc(z + N + N2, N2, &z_carry, 1);
+
+ clear_mem(workspace + N, N2);
+
+ bigint_cnd_add_or_sub(neg_mask, z + N2, workspace, 2*N-N2);
+ }
+
+/*
+* Karatsuba Squaring Operation
+*/
+void karatsuba_sqr(word z[], const word x[], size_t N, word workspace[])
+ {
+ if(N < KARATSUBA_SQUARE_THRESHOLD || N % 2)
+ {
+ switch(N)
+ {
+ case 6:
+ return bigint_comba_sqr6(z, x);
+ case 8:
+ return bigint_comba_sqr8(z, x);
+ case 9:
+ return bigint_comba_sqr9(z, x);
+ case 16:
+ return bigint_comba_sqr16(z, x);
+ case 24:
+ return bigint_comba_sqr24(z, x);
+ default:
+ return basecase_sqr(z, 2*N, x, N);
+ }
+ }
+
+ const size_t N2 = N / 2;
+
+ const word* x0 = x;
+ const word* x1 = x + N2;
+ word* z0 = z;
+ word* z1 = z + N;
+
+ word* ws0 = workspace;
+ word* ws1 = workspace + N;
+
+ clear_mem(workspace, 2*N);
+
+ // See comment in karatsuba_mul
+ bigint_sub_abs(z0, x0, x1, N2, workspace);
+ karatsuba_sqr(ws0, z0, N2, ws1);
+
+ karatsuba_sqr(z0, x0, N2, ws1);
+ karatsuba_sqr(z1, x1, N2, ws1);
+
+ const word ws_carry = bigint_add3_nc(ws1, z0, N, z1, N);
+ word z_carry = bigint_add2_nc(z + N2, N, ws1, N);
+
+ z_carry += bigint_add2_nc(z + N + N2, N2, &ws_carry, 1);
+ bigint_add2_nc(z + N + N2, N2, &z_carry, 1);
+
+ /*
+ * This is only actually required if cmp (result of bigint_sub_abs) is != 0,
+ * however if cmp==0 then ws0[0:N] == 0 and avoiding the jump hides a
+ * timing channel.
+ */
+ bigint_sub2(z + N2, 2*N-N2, ws0, N);
+ }
+
+/*
+* Pick a good size for the Karatsuba multiply
+*/
+size_t karatsuba_size(size_t z_size,
+ size_t x_size, size_t x_sw,
+ size_t y_size, size_t y_sw)
+ {
+ if(x_sw > x_size || x_sw > y_size || y_sw > x_size || y_sw > y_size)
+ return 0;
+
+ if(((x_size == x_sw) && (x_size % 2)) ||
+ ((y_size == y_sw) && (y_size % 2)))
+ return 0;
+
+ const size_t start = (x_sw > y_sw) ? x_sw : y_sw;
+ const size_t end = (x_size < y_size) ? x_size : y_size;
+
+ if(start == end)
+ {
+ if(start % 2)
+ return 0;
+ return start;
+ }
+
+ for(size_t j = start; j <= end; ++j)
+ {
+ if(j % 2)
+ continue;
+
+ if(2*j > z_size)
+ return 0;
+
+ if(x_sw <= j && j <= x_size && y_sw <= j && j <= y_size)
+ {
+ if(j % 4 == 2 &&
+ (j+2) <= x_size && (j+2) <= y_size && 2*(j+2) <= z_size)
+ return j+2;
+ return j;
+ }
+ }
+
+ return 0;
+ }
+
+/*
+* Pick a good size for the Karatsuba squaring
+*/
+size_t karatsuba_size(size_t z_size, size_t x_size, size_t x_sw)
+ {
+ if(x_sw == x_size)
+ {
+ if(x_sw % 2)
+ return 0;
+ return x_sw;
+ }
+
+ for(size_t j = x_sw; j <= x_size; ++j)
+ {
+ if(j % 2)
+ continue;
+
+ if(2*j > z_size)
+ return 0;
+
+ if(j % 4 == 2 && (j+2) <= x_size && 2*(j+2) <= z_size)
+ return j+2;
+ return j;
+ }
+
+ return 0;
+ }
+
+template<size_t SZ>
+inline bool sized_for_comba_mul(size_t x_sw, size_t x_size,
+ size_t y_sw, size_t y_size,
+ size_t z_size)
+ {
+ return (x_sw <= SZ && x_size >= SZ &&
+ y_sw <= SZ && y_size >= SZ &&
+ z_size >= 2*SZ);
+ }
+
+template<size_t SZ>
+inline bool sized_for_comba_sqr(size_t x_sw, size_t x_size,
+ size_t z_size)
+ {
+ return (x_sw <= SZ && x_size >= SZ && z_size >= 2*SZ);
+ }
+
+}
+
+void bigint_mul(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word y[], size_t y_size, size_t y_sw,
+ word workspace[], size_t ws_size)
+ {
+ clear_mem(z, z_size);
+
+ if(x_sw == 1)
+ {
+ bigint_linmul3(z, y, y_sw, x[0]);
+ }
+ else if(y_sw == 1)
+ {
+ bigint_linmul3(z, x, x_sw, y[0]);
+ }
+ else if(sized_for_comba_mul<4>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul4(z, x, y);
+ }
+ else if(sized_for_comba_mul<6>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul6(z, x, y);
+ }
+ else if(sized_for_comba_mul<8>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul8(z, x, y);
+ }
+ else if(sized_for_comba_mul<9>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul9(z, x, y);
+ }
+ else if(sized_for_comba_mul<16>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul16(z, x, y);
+ }
+ else if(sized_for_comba_mul<24>(x_sw, x_size, y_sw, y_size, z_size))
+ {
+ bigint_comba_mul24(z, x, y);
+ }
+ else if(x_sw < KARATSUBA_MULTIPLY_THRESHOLD ||
+ y_sw < KARATSUBA_MULTIPLY_THRESHOLD ||
+ !workspace)
+ {
+ basecase_mul(z, z_size, x, x_sw, y, y_sw);
+ }
+ else
+ {
+ const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);
+
+ if(N && z_size >= 2*N && ws_size >= 2*N)
+ karatsuba_mul(z, x, y, N, workspace);
+ else
+ basecase_mul(z, z_size, x, x_sw, y, y_sw);
+ }
+ }
+
+/*
+* Squaring Algorithm Dispatcher
+*/
+void bigint_sqr(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ word workspace[], size_t ws_size)
+ {
+ clear_mem(z, z_size);
+
+ BOTAN_ASSERT(z_size/2 >= x_sw, "Output size is sufficient");
+
+ if(x_sw == 1)
+ {
+ bigint_linmul3(z, x, x_sw, x[0]);
+ }
+ else if(sized_for_comba_sqr<4>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr4(z, x);
+ }
+ else if(sized_for_comba_sqr<6>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr6(z, x);
+ }
+ else if(sized_for_comba_sqr<8>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr8(z, x);
+ }
+ else if(sized_for_comba_sqr<9>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr9(z, x);
+ }
+ else if(sized_for_comba_sqr<16>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr16(z, x);
+ }
+ else if(sized_for_comba_sqr<24>(x_sw, x_size, z_size))
+ {
+ bigint_comba_sqr24(z, x);
+ }
+ else if(x_size < KARATSUBA_SQUARE_THRESHOLD || !workspace)
+ {
+ basecase_sqr(z, z_size, x, x_sw);
+ }
+ else
+ {
+ const size_t N = karatsuba_size(z_size, x_size, x_sw);
+
+ if(N && z_size >= 2*N && ws_size >= 2*N)
+ karatsuba_sqr(z, x, N, workspace);
+ else
+ basecase_sqr(z, z_size, x, x_sw);
+ }
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_madd.h b/comm/third_party/botan/src/lib/math/mp/mp_madd.h
new file mode 100644
index 0000000000..531d6e6634
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_madd.h
@@ -0,0 +1,146 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008,2013 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MP_WORD_MULADD_H_
+#define BOTAN_MP_WORD_MULADD_H_
+
+#include <botan/types.h>
+#include <botan/mul128.h>
+
+namespace Botan {
+
+#if (BOTAN_MP_WORD_BITS == 32)
+ typedef uint64_t dword;
+ #define BOTAN_HAS_MP_DWORD
+
+#elif (BOTAN_MP_WORD_BITS == 64)
+ #if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
+ typedef uint128_t dword;
+ #define BOTAN_HAS_MP_DWORD
+ #else
+ // No native 128 bit integer type; use mul64x64_128 instead
+ #endif
+
+#else
+ #error BOTAN_MP_WORD_BITS must be 32 or 64
+#endif
+
+#if defined(BOTAN_USE_GCC_INLINE_ASM)
+
+ #if defined(BOTAN_TARGET_ARCH_IS_X86_32) && (BOTAN_MP_WORD_BITS == 32)
+ #define BOTAN_MP_USE_X86_32_ASM
+ #elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && (BOTAN_MP_WORD_BITS == 64)
+ #define BOTAN_MP_USE_X86_64_ASM
+ #endif
+
+#endif
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(R"(
+ mull %[b]
+ addl %[c],%[a]
+ adcl $0,%[carry]
+ )"
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*c)
+ : "0"(a), "1"(b), [c]"g"(*c) : "cc");
+
+ return a;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+ asm(R"(
+ mulq %[b]
+ addq %[c],%[a]
+ adcq $0,%[carry]
+ )"
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*c)
+ : "0"(a), "1"(b), [c]"g"(*c) : "cc");
+
+ return a;
+
+#elif defined(BOTAN_HAS_MP_DWORD)
+ const dword s = static_cast<dword>(a) * b + *c;
+ *c = static_cast<word>(s >> BOTAN_MP_WORD_BITS);
+ return static_cast<word>(s);
+#else
+ static_assert(BOTAN_MP_WORD_BITS == 64, "Unexpected word size");
+
+ word hi = 0, lo = 0;
+
+ mul64x64_128(a, b, &lo, &hi);
+
+ lo += *c;
+ hi += (lo < *c); // carry?
+
+ *c = hi;
+ return lo;
+#endif
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+#if defined(BOTAN_MP_USE_X86_32_ASM)
+ asm(R"(
+ mull %[b]
+
+ addl %[c],%[a]
+ adcl $0,%[carry]
+
+ addl %[d],%[a]
+ adcl $0,%[carry]
+ )"
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*d)
+ : "0"(a), "1"(b), [c]"g"(c), [d]"g"(*d) : "cc");
+
+ return a;
+
+#elif defined(BOTAN_MP_USE_X86_64_ASM)
+ asm(R"(
+ mulq %[b]
+ addq %[c],%[a]
+ adcq $0,%[carry]
+ addq %[d],%[a]
+ adcq $0,%[carry]
+ )"
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*d)
+ : "0"(a), "1"(b), [c]"g"(c), [d]"g"(*d) : "cc");
+
+ return a;
+
+#elif defined(BOTAN_HAS_MP_DWORD)
+ const dword s = static_cast<dword>(a) * b + c + *d;
+ *d = static_cast<word>(s >> BOTAN_MP_WORD_BITS);
+ return static_cast<word>(s);
+#else
+ static_assert(BOTAN_MP_WORD_BITS == 64, "Unexpected word size");
+
+ word hi = 0, lo = 0;
+
+ mul64x64_128(a, b, &lo, &hi);
+
+ lo += c;
+ hi += (lo < c); // carry?
+
+ lo += *d;
+ hi += (lo < *d); // carry?
+
+ *d = hi;
+ return lo;
+#endif
+ }
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_monty.cpp b/comm/third_party/botan/src/lib/math/mp/mp_monty.cpp
new file mode 100644
index 0000000000..433d3ff358
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_monty.cpp
@@ -0,0 +1,133 @@
+/*
+* Montgomery Reduction
+* (C) 1999-2011 Jack Lloyd
+* 2006 Luca Piccarreta
+* 2016 Matthias Gierlings
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_monty.h>
+#include <botan/internal/mp_madd.h>
+#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
+#include <botan/mem_ops.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Montgomery reduction - product scanning form
+*
+* https://www.iacr.org/archive/ches2005/006.pdf
+* https://eprint.iacr.org/2013/882.pdf
+* https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/j37acmon.pdf
+*/
+void bigint_monty_redc_generic(word z[], size_t z_size,
+ const word p[], size_t p_size, word p_dash,
+ word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ w0 = z[0];
+
+ ws[0] = w0 * p_dash;
+
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+
+ w0 = w1;
+ w1 = w2;
+ w2 = 0;
+
+ for(size_t i = 1; i != p_size; ++i)
+ {
+ for(size_t j = 0; j < i; ++j)
+ {
+ word3_muladd(&w2, &w1, &w0, ws[j], p[i-j]);
+ }
+
+ word3_add(&w2, &w1, &w0, z[i]);
+
+ ws[i] = w0 * p_dash;
+
+ word3_muladd(&w2, &w1, &w0, ws[i], p[0]);
+
+ w0 = w1;
+ w1 = w2;
+ w2 = 0;
+ }
+
+ for(size_t i = 0; i != p_size; ++i)
+ {
+ for(size_t j = i + 1; j != p_size; ++j)
+ {
+ word3_muladd(&w2, &w1, &w0, ws[j], p[p_size + i-j]);
+ }
+
+ word3_add(&w2, &w1, &w0, z[p_size+i]);
+
+ ws[i] = w0;
+ w0 = w1;
+ w1 = w2;
+ w2 = 0;
+ }
+
+ word3_add(&w2, &w1, &w0, z[z_size-1]);
+
+ ws[p_size] = w0;
+ ws[p_size+1] = w1;
+
+ /*
+ * The result might need to be reduced mod p. To avoid a timing
+ * channel, always perform the subtraction. If in the compution
+ * of x - p a borrow is required then x was already < p.
+ *
+ * x starts at ws[0] and is p_size+1 bytes long.
+ * x - p starts at ws[p_size+1] and is also p_size+1 bytes log
+ *
+ * Select which address to copy from indexing off of the final
+ * borrow.
+ */
+
+ // word borrow = bigint_sub3(ws + p_size + 1, ws, p_size + 1, p, p_size);
+ word borrow = 0;
+ for(size_t i = 0; i != p_size; ++i)
+ ws[p_size + 1 + i] = word_sub(ws[i], p[i], &borrow);
+ ws[2*p_size+1] = word_sub(ws[p_size], 0, &borrow);
+
+ BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1);
+
+ CT::conditional_copy_mem(borrow, z, ws, ws + (p_size + 1), (p_size + 1));
+ clear_mem(z + p_size, z_size - p_size - 2);
+ }
+
+}
+
+void bigint_monty_redc(word z[],
+ const word p[], size_t p_size, word p_dash,
+ word ws[], size_t ws_size)
+ {
+ const size_t z_size = 2*(p_size+1);
+
+ BOTAN_ARG_CHECK(ws_size >= z_size, "workspace too small");
+
+ if(p_size == 4)
+ bigint_monty_redc_4(z, p, p_dash, ws);
+ else if(p_size == 6)
+ bigint_monty_redc_6(z, p, p_dash, ws);
+ else if(p_size == 8)
+ bigint_monty_redc_8(z, p, p_dash, ws);
+ else if(p_size == 16)
+ bigint_monty_redc_16(z, p, p_dash, ws);
+ else if(p_size == 24)
+ bigint_monty_redc_24(z, p, p_dash, ws);
+ else if(p_size == 32)
+ bigint_monty_redc_32(z, p, p_dash, ws);
+ else
+ bigint_monty_redc_generic(z, z_size, p, p_size, p_dash, ws);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_monty.h b/comm/third_party/botan/src/lib/math/mp/mp_monty.h
new file mode 100644
index 0000000000..7462272d5c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_monty.h
@@ -0,0 +1,31 @@
+/*
+* (C) 2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MP_MONTY_H_
+#define BOTAN_MP_MONTY_H_
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Each of these functions makes the following assumptions:
+*
+* z_size >= 2*(p_size + 1)
+* ws_size >= z_size
+*/
+
+void bigint_monty_redc_4(word z[], const word p[], word p_dash, word ws[]);
+void bigint_monty_redc_6(word z[], const word p[], word p_dash, word ws[]);
+void bigint_monty_redc_8(word z[], const word p[], word p_dash, word ws[]);
+void bigint_monty_redc_16(word z[], const word p[], word p_dash, word ws[]);
+void bigint_monty_redc_24(word z[], const word p[], word p_dash, word ws[]);
+void bigint_monty_redc_32(word z[], const word p[], word p_dash, word ws[]);
+
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/math/mp/mp_monty_n.cpp b/comm/third_party/botan/src/lib/math/mp/mp_monty_n.cpp
new file mode 100644
index 0000000000..0331d4a073
--- /dev/null
+++ b/comm/third_party/botan/src/lib/math/mp/mp_monty_n.cpp
@@ -0,0 +1,2614 @@
+/*
+* This file was automatically generated by ./src/scripts/monty.py on 2018-06-11
+* All manual changes will be lost. Edit the script instead.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/mp_monty.h>
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+void bigint_monty_redc_4(word z[], const word p[4], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[4] = w0;
+ ws[5] = w1;
+ word borrow = 0;
+ ws[5] = word_sub(ws[0], p[0], &borrow);
+ ws[6] = word_sub(ws[1], p[1], &borrow);
+ ws[7] = word_sub(ws[2], p[2], &borrow);
+ ws[8] = word_sub(ws[3], p[3], &borrow);
+ ws[9] = word_sub(ws[4], 0, &borrow);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 5, 5);
+ clear_mem(z + 4, 2*(4+1) - 4);
+ }
+
+void bigint_monty_redc_6(word z[], const word p[6], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[4] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[1]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[5] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[1]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[2]);
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[3]);
+ word3_add(&w2, &w1, &w0, z[8]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[4]);
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[5]);
+ word3_add(&w2, &w1, &w0, z[10]);
+ ws[4] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[11]);
+ ws[5] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[13]);
+ ws[6] = w0;
+ ws[7] = w1;
+ word borrow = 0;
+ ws[7] = word_sub(ws[0], p[0], &borrow);
+ ws[8] = word_sub(ws[1], p[1], &borrow);
+ ws[9] = word_sub(ws[2], p[2], &borrow);
+ ws[10] = word_sub(ws[3], p[3], &borrow);
+ ws[11] = word_sub(ws[4], p[4], &borrow);
+ ws[12] = word_sub(ws[5], p[5], &borrow);
+ ws[13] = word_sub(ws[6], 0, &borrow);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 7, 7);
+ clear_mem(z + 6, 2*(6+1) - 6);
+ }
+
+void bigint_monty_redc_8(word z[], const word p[8], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[4] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[1]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[5] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[1]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[6] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[1]);
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[7] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[1]);
+ word3_add(&w2, &w1, &w0, z[8]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[2]);
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[3]);
+ word3_add(&w2, &w1, &w0, z[10]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[4]);
+ word3_add(&w2, &w1, &w0, z[11]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[5]);
+ word3_add(&w2, &w1, &w0, z[12]);
+ ws[4] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[6]);
+ word3_add(&w2, &w1, &w0, z[13]);
+ ws[5] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[7]);
+ word3_add(&w2, &w1, &w0, z[14]);
+ ws[6] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[15]);
+ ws[7] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[17]);
+ ws[8] = w0;
+ ws[9] = w1;
+ word borrow = 0;
+ ws[9] = word_sub(ws[0], p[0], &borrow);
+ ws[10] = word_sub(ws[1], p[1], &borrow);
+ ws[11] = word_sub(ws[2], p[2], &borrow);
+ ws[12] = word_sub(ws[3], p[3], &borrow);
+ ws[13] = word_sub(ws[4], p[4], &borrow);
+ ws[14] = word_sub(ws[5], p[5], &borrow);
+ ws[15] = word_sub(ws[6], p[6], &borrow);
+ ws[16] = word_sub(ws[7], p[7], &borrow);
+ ws[17] = word_sub(ws[8], 0, &borrow);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 9, 9);
+ clear_mem(z + 8, 2*(8+1) - 8);
+ }
+
+void bigint_monty_redc_16(word z[], const word p[16], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[4] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[1]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[5] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[1]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[6] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[1]);
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[7] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[1]);
+ word3_add(&w2, &w1, &w0, z[8]);
+ ws[8] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[1]);
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[9] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[1]);
+ word3_add(&w2, &w1, &w0, z[10]);
+ ws[10] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[1]);
+ word3_add(&w2, &w1, &w0, z[11]);
+ ws[11] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[1]);
+ word3_add(&w2, &w1, &w0, z[12]);
+ ws[12] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[1]);
+ word3_add(&w2, &w1, &w0, z[13]);
+ ws[13] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[1]);
+ word3_add(&w2, &w1, &w0, z[14]);
+ ws[14] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[1]);
+ word3_add(&w2, &w1, &w0, z[15]);
+ ws[15] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[1]);
+ word3_add(&w2, &w1, &w0, z[16]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[2]);
+ word3_add(&w2, &w1, &w0, z[17]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[3]);
+ word3_add(&w2, &w1, &w0, z[18]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[4]);
+ word3_add(&w2, &w1, &w0, z[19]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[5]);
+ word3_add(&w2, &w1, &w0, z[20]);
+ ws[4] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[6]);
+ word3_add(&w2, &w1, &w0, z[21]);
+ ws[5] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[7]);
+ word3_add(&w2, &w1, &w0, z[22]);
+ ws[6] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[8]);
+ word3_add(&w2, &w1, &w0, z[23]);
+ ws[7] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[9]);
+ word3_add(&w2, &w1, &w0, z[24]);
+ ws[8] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[10]);
+ word3_add(&w2, &w1, &w0, z[25]);
+ ws[9] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[11]);
+ word3_add(&w2, &w1, &w0, z[26]);
+ ws[10] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[12]);
+ word3_add(&w2, &w1, &w0, z[27]);
+ ws[11] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[13]);
+ word3_add(&w2, &w1, &w0, z[28]);
+ ws[12] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[14]);
+ word3_add(&w2, &w1, &w0, z[29]);
+ ws[13] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[15]);
+ word3_add(&w2, &w1, &w0, z[30]);
+ ws[14] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[31]);
+ ws[15] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[33]);
+ ws[16] = w0;
+ ws[17] = w1;
+ word borrow = bigint_sub3(ws + 16 + 1, ws, 16 + 1, p, 16);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 17, 17);
+ clear_mem(z + 16, 2*(16+1) - 16);
+ }
+
+void bigint_monty_redc_24(word z[], const word p[24], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[4] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[1]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[5] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[1]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[6] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[1]);
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[7] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[1]);
+ word3_add(&w2, &w1, &w0, z[8]);
+ ws[8] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[1]);
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[9] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[1]);
+ word3_add(&w2, &w1, &w0, z[10]);
+ ws[10] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[1]);
+ word3_add(&w2, &w1, &w0, z[11]);
+ ws[11] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[1]);
+ word3_add(&w2, &w1, &w0, z[12]);
+ ws[12] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[1]);
+ word3_add(&w2, &w1, &w0, z[13]);
+ ws[13] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[1]);
+ word3_add(&w2, &w1, &w0, z[14]);
+ ws[14] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[1]);
+ word3_add(&w2, &w1, &w0, z[15]);
+ ws[15] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[1]);
+ word3_add(&w2, &w1, &w0, z[16]);
+ ws[16] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[16], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[1]);
+ word3_add(&w2, &w1, &w0, z[17]);
+ ws[17] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[17], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[1]);
+ word3_add(&w2, &w1, &w0, z[18]);
+ ws[18] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[18], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[1]);
+ word3_add(&w2, &w1, &w0, z[19]);
+ ws[19] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[19], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[1]);
+ word3_add(&w2, &w1, &w0, z[20]);
+ ws[20] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[20], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[1]);
+ word3_add(&w2, &w1, &w0, z[21]);
+ ws[21] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[21], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[1]);
+ word3_add(&w2, &w1, &w0, z[22]);
+ ws[22] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[22], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[1]);
+ word3_add(&w2, &w1, &w0, z[23]);
+ ws[23] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[23], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[1]);
+ word3_add(&w2, &w1, &w0, z[24]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[2]);
+ word3_add(&w2, &w1, &w0, z[25]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[3]);
+ word3_add(&w2, &w1, &w0, z[26]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[4]);
+ word3_add(&w2, &w1, &w0, z[27]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[5]);
+ word3_add(&w2, &w1, &w0, z[28]);
+ ws[4] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[6]);
+ word3_add(&w2, &w1, &w0, z[29]);
+ ws[5] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[7]);
+ word3_add(&w2, &w1, &w0, z[30]);
+ ws[6] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[8]);
+ word3_add(&w2, &w1, &w0, z[31]);
+ ws[7] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[9]);
+ word3_add(&w2, &w1, &w0, z[32]);
+ ws[8] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[10]);
+ word3_add(&w2, &w1, &w0, z[33]);
+ ws[9] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[11]);
+ word3_add(&w2, &w1, &w0, z[34]);
+ ws[10] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[12]);
+ word3_add(&w2, &w1, &w0, z[35]);
+ ws[11] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[13]);
+ word3_add(&w2, &w1, &w0, z[36]);
+ ws[12] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[14]);
+ word3_add(&w2, &w1, &w0, z[37]);
+ ws[13] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[15]);
+ word3_add(&w2, &w1, &w0, z[38]);
+ ws[14] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[16], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[16]);
+ word3_add(&w2, &w1, &w0, z[39]);
+ ws[15] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[17], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[17]);
+ word3_add(&w2, &w1, &w0, z[40]);
+ ws[16] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[18], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[18]);
+ word3_add(&w2, &w1, &w0, z[41]);
+ ws[17] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[19], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[19]);
+ word3_add(&w2, &w1, &w0, z[42]);
+ ws[18] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[20], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[20]);
+ word3_add(&w2, &w1, &w0, z[43]);
+ ws[19] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[21], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[21]);
+ word3_add(&w2, &w1, &w0, z[44]);
+ ws[20] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[22], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[22]);
+ word3_add(&w2, &w1, &w0, z[45]);
+ ws[21] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[23], p[23]);
+ word3_add(&w2, &w1, &w0, z[46]);
+ ws[22] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[47]);
+ ws[23] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[49]);
+ ws[24] = w0;
+ ws[25] = w1;
+ word borrow = bigint_sub3(ws + 24 + 1, ws, 24 + 1, p, 24);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 25, 25);
+ clear_mem(z + 24, 2*(24+1) - 24);
+ }
+
+void bigint_monty_redc_32(word z[], const word p[32], word p_dash, word ws[])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+ w0 = z[0];
+ ws[0] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[1]);
+ word3_add(&w2, &w1, &w0, z[1]);
+ ws[1] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[1]);
+ word3_add(&w2, &w1, &w0, z[2]);
+ ws[2] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[1]);
+ word3_add(&w2, &w1, &w0, z[3]);
+ ws[3] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[1]);
+ word3_add(&w2, &w1, &w0, z[4]);
+ ws[4] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[1]);
+ word3_add(&w2, &w1, &w0, z[5]);
+ ws[5] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[1]);
+ word3_add(&w2, &w1, &w0, z[6]);
+ ws[6] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[1]);
+ word3_add(&w2, &w1, &w0, z[7]);
+ ws[7] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[1]);
+ word3_add(&w2, &w1, &w0, z[8]);
+ ws[8] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[1]);
+ word3_add(&w2, &w1, &w0, z[9]);
+ ws[9] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[1]);
+ word3_add(&w2, &w1, &w0, z[10]);
+ ws[10] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[1]);
+ word3_add(&w2, &w1, &w0, z[11]);
+ ws[11] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[1]);
+ word3_add(&w2, &w1, &w0, z[12]);
+ ws[12] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[1]);
+ word3_add(&w2, &w1, &w0, z[13]);
+ ws[13] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[1]);
+ word3_add(&w2, &w1, &w0, z[14]);
+ ws[14] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[1]);
+ word3_add(&w2, &w1, &w0, z[15]);
+ ws[15] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[1]);
+ word3_add(&w2, &w1, &w0, z[16]);
+ ws[16] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[16], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[1]);
+ word3_add(&w2, &w1, &w0, z[17]);
+ ws[17] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[17], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[1]);
+ word3_add(&w2, &w1, &w0, z[18]);
+ ws[18] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[18], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[1]);
+ word3_add(&w2, &w1, &w0, z[19]);
+ ws[19] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[19], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[1]);
+ word3_add(&w2, &w1, &w0, z[20]);
+ ws[20] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[20], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[1]);
+ word3_add(&w2, &w1, &w0, z[21]);
+ ws[21] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[21], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[1]);
+ word3_add(&w2, &w1, &w0, z[22]);
+ ws[22] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[22], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[1]);
+ word3_add(&w2, &w1, &w0, z[23]);
+ ws[23] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[23], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[1]);
+ word3_add(&w2, &w1, &w0, z[24]);
+ ws[24] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[24], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[1]);
+ word3_add(&w2, &w1, &w0, z[25]);
+ ws[25] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[25], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[1]);
+ word3_add(&w2, &w1, &w0, z[26]);
+ ws[26] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[26], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[1]);
+ word3_add(&w2, &w1, &w0, z[27]);
+ ws[27] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[27], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[1]);
+ word3_add(&w2, &w1, &w0, z[28]);
+ ws[28] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[28], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[1]);
+ word3_add(&w2, &w1, &w0, z[29]);
+ ws[29] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[29], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[1]);
+ word3_add(&w2, &w1, &w0, z[30]);
+ ws[30] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[30], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[0], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[1], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[1]);
+ word3_add(&w2, &w1, &w0, z[31]);
+ ws[31] = w0 * p_dash;
+ word3_muladd(&w2, &w1, &w0, ws[31], p[0]);
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[1], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[2], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[2]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[1]);
+ word3_add(&w2, &w1, &w0, z[32]);
+ ws[0] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[2], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[3], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[3]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[2]);
+ word3_add(&w2, &w1, &w0, z[33]);
+ ws[1] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[3], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[4], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[4]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[3]);
+ word3_add(&w2, &w1, &w0, z[34]);
+ ws[2] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[4], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[5], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[5]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[4]);
+ word3_add(&w2, &w1, &w0, z[35]);
+ ws[3] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[5], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[6], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[6]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[5]);
+ word3_add(&w2, &w1, &w0, z[36]);
+ ws[4] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[6], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[7], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[7]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[6]);
+ word3_add(&w2, &w1, &w0, z[37]);
+ ws[5] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[7], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[8], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[8]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[7]);
+ word3_add(&w2, &w1, &w0, z[38]);
+ ws[6] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[8], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[9], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[9]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[8]);
+ word3_add(&w2, &w1, &w0, z[39]);
+ ws[7] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[9], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[10], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[10]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[9]);
+ word3_add(&w2, &w1, &w0, z[40]);
+ ws[8] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[10], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[11], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[11]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[10]);
+ word3_add(&w2, &w1, &w0, z[41]);
+ ws[9] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[11], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[12], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[12]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[11]);
+ word3_add(&w2, &w1, &w0, z[42]);
+ ws[10] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[12], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[13], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[13]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[12]);
+ word3_add(&w2, &w1, &w0, z[43]);
+ ws[11] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[13], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[14], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[14]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[13]);
+ word3_add(&w2, &w1, &w0, z[44]);
+ ws[12] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[14], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[15], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[15]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[14]);
+ word3_add(&w2, &w1, &w0, z[45]);
+ ws[13] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[15], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[16], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[16]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[15]);
+ word3_add(&w2, &w1, &w0, z[46]);
+ ws[14] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[16], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[17], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[17]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[16]);
+ word3_add(&w2, &w1, &w0, z[47]);
+ ws[15] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[17], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[18], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[18]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[17]);
+ word3_add(&w2, &w1, &w0, z[48]);
+ ws[16] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[18], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[19], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[19]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[18]);
+ word3_add(&w2, &w1, &w0, z[49]);
+ ws[17] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[19], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[20], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[20]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[19]);
+ word3_add(&w2, &w1, &w0, z[50]);
+ ws[18] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[20], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[21], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[21]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[20]);
+ word3_add(&w2, &w1, &w0, z[51]);
+ ws[19] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[21], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[22], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[22]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[21]);
+ word3_add(&w2, &w1, &w0, z[52]);
+ ws[20] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[22], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[23], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[23]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[22]);
+ word3_add(&w2, &w1, &w0, z[53]);
+ ws[21] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[23], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[24], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[24]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[23]);
+ word3_add(&w2, &w1, &w0, z[54]);
+ ws[22] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[24], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[25], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[25]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[24]);
+ word3_add(&w2, &w1, &w0, z[55]);
+ ws[23] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[25], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[26], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[26]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[25]);
+ word3_add(&w2, &w1, &w0, z[56]);
+ ws[24] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[26], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[27], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[27]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[26]);
+ word3_add(&w2, &w1, &w0, z[57]);
+ ws[25] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[27], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[28], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[28]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[27]);
+ word3_add(&w2, &w1, &w0, z[58]);
+ ws[26] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[28], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[29], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[29]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[28]);
+ word3_add(&w2, &w1, &w0, z[59]);
+ ws[27] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[29], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[30], p[30]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[29]);
+ word3_add(&w2, &w1, &w0, z[60]);
+ ws[28] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[30], p[31]);
+ word3_muladd(&w2, &w1, &w0, ws[31], p[30]);
+ word3_add(&w2, &w1, &w0, z[61]);
+ ws[29] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_muladd(&w2, &w1, &w0, ws[31], p[31]);
+ word3_add(&w2, &w1, &w0, z[62]);
+ ws[30] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[63]);
+ ws[31] = w0;
+ w0 = w1; w1 = w2; w2 = 0;
+ word3_add(&w2, &w1, &w0, z[65]);
+ ws[32] = w0;
+ ws[33] = w1;
+ word borrow = bigint_sub3(ws + 32 + 1, ws, 32 + 1, p, 32);
+ CT::conditional_copy_mem(borrow, z, ws, ws + 33, 33);
+ clear_mem(z + 32, 2*(32+1) - 32);
+ }
+
+}