packages feed

crypton 2.2.2 → 2.2.3

raw patch · 8 files changed

+3992/−49 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,18 @@ # CHANGELOG for crypton +## 2.2.3++**crypton builds on Windows again.**  2.2.2's tarball lacked a header that+only Windows includes, so it built from git but not from Hackage.  With+2.2.2, `-f-support_s2n_bignum` works around it.++* bench: RSA-3072 in the tables+  [#331](https://github.com/kazu-yamamoto/crypton/pull/331)+* perf(rsa): a generated Montgomery squaring for AArch64+  [#333](https://github.com/kazu-yamamoto/crypton/pull/333)+* fix: ship the Windows wrapper for s2n-bignum+  [#334](https://github.com/kazu-yamamoto/crypton/pull/334)+ ## 2.2.2  **crypton builds on an Intel Mac again.**  From 2.1.2 onwards, Apple's
README.md view
@@ -111,31 +111,33 @@  Throughput in MB/s, **higher is better**: -| | crypton 1.1.5 | crypton 2.2.1 | OpenSSL | 2.2.1 / OpenSSL |+| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | 2.2.2 / OpenSSL | | --- | ---: | ---: | ---: | ---: |-| AES-128-GCM | 1335 | **6037** | 4053 | 1.49 |-| AES-256-GCM | 1093 | **5487** | 3786 | 1.45 |-| ChaCha20-Poly1305 | 399 | 2196 | 2214 | 0.99 |-| SHA-1 | 729 | 1681 | 1679 | 1.00 |-| SHA-256 | 290 | 1586 | 1578 | 1.00 |-| SHA-512 | 448 | 770 | 749 | 1.03 |-| SHA3-256 | 109 | 422 | 427 | 0.99 |+| AES-128-GCM | 1336 | **6037** | 4050 | 1.49 |+| AES-256-GCM | 1093 | **5490** | 3769 | 1.46 |+| ChaCha20-Poly1305 | 399 | 2196 | 2222 | 0.99 |+| SHA-1 | 729 | 1663 | 1682 | 0.99 |+| SHA-256 | 289 | 1586 | 1579 | 1.00 |+| SHA-512 | 448 | 770 | 750 | 1.03 |+| SHA3-256 | 109 | 421 | 425 | 0.99 |  Time per operation in microseconds, **lower is better**: -| | crypton 1.1.5 | crypton 2.2.1 | OpenSSL | OpenSSL / 2.2.1 |+| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | OpenSSL / 2.2.2 | | --- | ---: | ---: | ---: | ---: |-| X25519 | 44.27 | 28.55 | 36.49 | 1.28 |-| ECDH P-256 | 164.8 | 50.57 | 51.50 | 1.02 |-| ECDH P-384 | 2242 | **163.8** | 850.3 | 5.19 |-| Ed25519 sign | 29.61 | 18.62 | 33.70 | 1.81 |-| Ed25519 verify | 48.47 | 48.01 | 109.9 | 2.29 |-| ECDSA P-256 sign | 81.23 | 18.90 | 21.93 | 1.16 |-| ECDSA P-256 verify | 233.5 | 70.52 | 67.76 | 0.96 |-| ECDSA P-384 sign | 2262 | **303.6** | 895.7 | 2.95 |-| ECDSA P-384 verify | 2682 | **471.5** | 725.4 | 1.54 |-| RSA-2048 sign/decrypt | 758.2 | 616.2 | 658.3 | 1.07 |-| RSA-2048 verify/encrypt | 33.01 | 30.12 | 18.86 | 0.63 |+| X25519 | 44.06 | 28.54 | 36.50 | 1.28 |+| ECDH P-256 | 164.5 | 50.56 | 51.62 | 1.02 |+| ECDH P-384 | 2241 | **164.3** | 833.3 | 5.07 |+| Ed25519 sign | 29.78 | 18.61 | 33.51 | 1.80 |+| Ed25519 verify | 48.32 | 48.14 | 110.1 | 2.29 |+| ECDSA P-256 sign | 81.62 | 18.71 | 21.96 | 1.17 |+| ECDSA P-256 verify | 232.0 | 70.32 | 67.53 | 0.96 |+| ECDSA P-384 sign | 2270 | **304.1** | 880.3 | 2.89 |+| ECDSA P-384 verify | 2678 | **472.0** | 722.1 | 1.53 |+| RSA-2048 sign/decrypt | 759.7 | 614.3 | 659.2 | 1.07 |+| RSA-2048 verify/encrypt | 33.19 | 28.09 | 18.85 | 0.67 |+| RSA-3072 sign/decrypt | 2500 | 2316 | 2008 | 0.87 |+| RSA-3072 verify/encrypt | 65.97 | 63.47 | 40.12 | 0.63 |  ### AArch64 @@ -144,35 +146,37 @@  Throughput in MB/s, **higher is better**: -| | crypton 1.1.5 | crypton 2.2.1 | OpenSSL | 2.2.1 / OpenSSL |+| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | 2.2.2 / OpenSSL | | --- | ---: | ---: | ---: | ---: |-| AES-128-GCM | 127 | **11753** | 10748 | 1.09 |-| AES-256-GCM | 98 | **9834** | 9130 | 1.08 |-| ChaCha20-Poly1305 | 755 | 2232 | 2235 | 1.00 |-| SHA-1 | 1200 | 3382 | 3339 | 1.01 |-| SHA-256 | 473 | 3395 | 3309 | 1.03 |-| SHA-512 | 727 | 1854 | 1816 | 1.02 |-| SHA3-256 | 550 | 1076 | 1075 | 1.00 |+| AES-128-GCM | 127 | **11661** | 10764 | 1.08 |+| AES-256-GCM | 98 | **9764** | 9187 | 1.06 |+| ChaCha20-Poly1305 | 767 | 2249 | 2263 | 0.99 |+| SHA-1 | 1215 | 3383 | 3357 | 1.01 |+| SHA-256 | 478 | 3391 | 3353 | 1.01 |+| SHA-512 | 733 | 1847 | 1835 | 1.01 |+| SHA3-256 | 549 | 1084 | 1073 | 1.01 |  Time per operation in microseconds, **lower is better**: -| | crypton 1.1.5 | crypton 2.2.1 | OpenSSL | OpenSSL / 2.2.1 |+| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | OpenSSL / 2.2.2 | | --- | ---: | ---: | ---: | ---: |-| X25519 | 18.15 | **11.65** | 15.38 | 1.32 |-| ECDH P-256 | 69.23 | **19.62** | 24.47 | 1.25 |-| ECDH P-384 | 3322 | **73.42** | 370.9 | 5.05 |-| Ed25519 sign | 13.27 | **7.983** | 13.24 | 1.66 |-| Ed25519 verify | 18.32 | 18.20 | 34.05 | 1.87 |-| ECDSA P-256 sign | 32.02 | **6.983** | 10.73 | 1.54 |-| ECDSA P-256 verify | 94.30 | **27.10** | 32.46 | 1.20 |-| ECDSA P-384 sign | 3256 | **124.7** | 392.4 | 3.15 |-| ECDSA P-384 verify | 3896 | **203.5** | 329.4 | 1.62 |-| RSA-2048 sign/decrypt | 448.6 | 458.6 | 320.1 | 0.70 |-| RSA-2048 verify/encrypt | 18.27 | 15.20 | 8.421 | 0.55 |+| X25519 | 18.27 | **11.55** | 15.38 | 1.33 |+| ECDH P-256 | 68.80 | **20.15** | 24.45 | 1.21 |+| ECDH P-384 | 3277 | **72.17** | 374.3 | 5.19 |+| Ed25519 sign | 13.42 | **7.450** | 13.27 | 1.78 |+| Ed25519 verify | 18.30 | 18.30 | 34.44 | 1.88 |+| ECDSA P-256 sign | 32.13 | **6.417** | 10.68 | 1.66 |+| ECDSA P-256 verify | 95.07 | **26.68** | 32.27 | 1.21 |+| ECDSA P-384 sign | 3241 | **124.7** | 392.8 | 3.15 |+| ECDSA P-384 verify | 3885 | **203.8** | 329.3 | 1.62 |+| RSA-2048 sign/decrypt | 451.0 | 458.7 | 320.3 | 0.70 |+| RSA-2048 verify/encrypt | 18.12 | 15.58 | 8.400 | 0.54 |+| RSA-3072 sign/decrypt | 1474 | 1317 | 927.7 | 0.70 |+| RSA-3072 verify/encrypt | 47.85 | 44.20 | 17.84 | 0.40 |  ### What the numbers say -There are two changes behind the 1.1.5 column and the 2.2.1 one, not a+There are two changes behind the 1.1.5 column and the 2.2.2 one, not a single steady improvement.  The first, in 2.0.0, was a rewrite: the bulk algorithms moved into C, the@@ -210,11 +214,11 @@ hiding the exponent is what the difference bought.  On x86-64 that cost is more than repaid -- s2n-bignum's Montgomery multiplication is twice the C's, because the C cannot form the two carry chains `ADCX` and `ADOX` give, and-2.2.1 signs in less than 1.1.5 took while keeping what 2.0.0 gained.  On-AArch64 there is nothing to use: s2n-bignum has no generic routine for it,-and the same five that help on x86-64 measure level with the C there, so the-C stays and the gap with it.  No portable C closes that gap either -- the-measurements are in+2.2.2 signs in less than 1.1.5 took, at 3072 bits as well as 2048, while+keeping what 2.0.0 gained.  On AArch64 there is nothing to use: s2n-bignum's+routines there, the five that help on x86-64 and the generic ones alike,+measure no better than the C, so the C stays and the gap with it.  No+portable C closes that gap either -- the measurements are in [#275](https://github.com/kazu-yamamoto/crypton/issues/275).  Verification does not move much either way: its exponent is 65537, seventeen bits, and there is no exponentiation to speak of.@@ -236,7 +240,7 @@ takes a block at a time where crypton takes two.  The same idea as theirs, one step further down the feature ladder; not a better one. -The 512-bit path arrived after 2.1.2, so it is in the 2.2.1 column -- but+The 512-bit path arrived after 2.1.2, so it is in the 2.2.2 column -- but neither machine in the tables above has AVX-512, so neither column shows it. On the runners that do, measured over 16 KiB in MB/s: an EPYC 9V45 (Zen 5) goes from 9616 to 14268 with it, a Xeon 6973P-C from 8095 to 9848, a Xeon@@ -261,7 +265,7 @@ key from the secret key every time it signs, so that a caller who passes a public key that does not match cannot be made to leak the private one.  That costs a second scalar multiplication, which OpenSSL's signing does not pay ---and the row is still 1.66 on AArch64 and 1.81 on x86-64, so the safety is had+and the row is still 1.78 on AArch64 and 1.80 on x86-64, so the safety is had for nothing here rather than paid for.  Ed25519 verification wanted one too, for an unhappier reason, and 2.2.1
+ cbits/crypton_mont_sqr.h view
@@ -0,0 +1,3751 @@+/* Generated by cbits/crypton_mont_sqr.py; do not edit.+ *+ * Montgomery squaring for AArch64 at 16, 24 and 32 limbs, the halves of+ * RSA-2048, -3072 and -4096.  Each answers what mont_sqr answers. */+#ifndef CRYPTON_MONT_SQR_H+#define CRYPTON_MONT_SQR_H++#include "crypton_bignum.h"++/* (t2:t1:t0) += x * y */+#define MONT_SQR_MAC(t0, t1, t2, x, y)                                  \+	do {                                                                \+		limb_t lo_, hi_;                                                \+		__asm__("mul\t%0, %5, %6\n\t"                                   \+		        "umulh\t%1, %5, %6\n\t"                                 \+		        "adds\t%2, %2, %0\n\t"                                  \+		        "adcs\t%3, %3, %1\n\t"                                  \+		        "adc\t%4, %4, xzr"                                       \+		        : "=&r"(lo_), "=&r"(hi_), "+r"(t0), "+r"(t1), "+r"(t2)  \+		        : "r"(x), "r"(y)                                        \+		        : "cc");                                                \+	} while (0)++/* (s2:s1:s0) = x * y */+#define MONT_SQR_MUL(s0, s1, s2, x, y)                                  \+	__asm__("mul\t%0, %3, %4\n\t"                                       \+	        "umulh\t%1, %3, %4\n\t"                                     \+	        "mov\t%2, xzr"                                               \+	        : "=&r"(s0), "=&r"(s1), "=r"(s2)                            \+	        : "r"(x), "r"(y))++/* (t2:t1:t0) += 2 * (s2:s1:s0) */+#define MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2)                           \+	do {                                                                \+		s2 = (s2 << 1) | (s1 >> 63);                                    \+		s1 = (s1 << 1) | (s0 >> 63);                                    \+		s0 <<= 1;                                                       \+		__asm__("adds\t%0, %0, %3\n\t"                                  \+		        "adcs\t%1, %1, %4\n\t"                                  \+		        "adc\t%2, %2, %5"                                        \+		        : "+r"(t0), "+r"(t1), "+r"(t2)                          \+		        : "r"(s0), "r"(s1), "r"(s2)                             \+		        : "cc");                                                \+	} while (0)++/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */+static void crypton_mont_sqr16(limb_t *r, const limb_t *a, const limb_t *m,+                               limb_t n0, limb_t *t)+{+	limb_t *u = t, *z = t + 16;+	limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;++	/* column 0 */+	MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);+	u[0] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 1 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);+	u[1] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 2 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);+	u[2] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 3 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);+	u[3] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 4 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);+	u[4] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 5 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);+	u[5] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 6 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);+	u[6] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 7 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);+	u[7] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 8 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);+	u[8] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 9 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);+	u[9] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 10 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);+	u[10] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 11 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);+	u[11] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 12 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);+	u[12] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 13 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);+	u[13] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 14 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);+	u[14] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 15 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);+	u[15] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 16 */+	MONT_SQR_MUL(s0, s1, s2, a[1], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);+	z[0] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 17 */+	MONT_SQR_MUL(s0, s1, s2, a[2], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);+	z[1] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 18 */+	MONT_SQR_MUL(s0, s1, s2, a[3], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);+	z[2] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 19 */+	MONT_SQR_MUL(s0, s1, s2, a[4], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);+	z[3] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 20 */+	MONT_SQR_MUL(s0, s1, s2, a[5], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);+	z[4] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 21 */+	MONT_SQR_MUL(s0, s1, s2, a[6], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);+	z[5] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 22 */+	MONT_SQR_MUL(s0, s1, s2, a[7], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);+	z[6] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 23 */+	MONT_SQR_MUL(s0, s1, s2, a[8], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);+	z[7] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 24 */+	MONT_SQR_MUL(s0, s1, s2, a[9], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);+	z[8] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 25 */+	MONT_SQR_MUL(s0, s1, s2, a[10], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);+	z[9] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 26 */+	MONT_SQR_MUL(s0, s1, s2, a[11], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);+	z[10] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 27 */+	MONT_SQR_MUL(s0, s1, s2, a[12], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);+	z[11] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 28 */+	MONT_SQR_MUL(s0, s1, s2, a[13], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);+	z[12] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 29 */+	MONT_SQR_MUL(s0, s1, s2, a[14], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);+	z[13] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 30 */+	MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);+	z[14] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	z[15] = t0;++	/* under 2m, with t1 the bit above n limbs: at most one subtraction */+	borrow = sub_n(r, z, m, 16);+	take = t1 | (borrow ^ 1);+	select_n(r, r, z, take & 1, 16);+}++/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */+static void crypton_mont_sqr24(limb_t *r, const limb_t *a, const limb_t *m,+                               limb_t n0, limb_t *t)+{+	limb_t *u = t, *z = t + 24;+	limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;++	/* column 0 */+	MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);+	u[0] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 1 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);+	u[1] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 2 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);+	u[2] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 3 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);+	u[3] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 4 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);+	u[4] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 5 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);+	u[5] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 6 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);+	u[6] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 7 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);+	u[7] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 8 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);+	u[8] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 9 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);+	u[9] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 10 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);+	u[10] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 11 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);+	u[11] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 12 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);+	u[12] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 13 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);+	u[13] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 14 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);+	u[14] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 15 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);+	u[15] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 16 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);+	u[16] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[16], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 17 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[1]);+	u[17] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[17], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 18 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[1]);+	u[18] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[18], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 19 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[1]);+	u[19] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[19], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 20 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[1]);+	u[20] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[20], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 21 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[1]);+	u[21] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[21], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 22 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[1]);+	u[22] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[22], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 23 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[1]);+	u[23] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[23], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 24 */+	MONT_SQR_MUL(s0, s1, s2, a[1], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[1]);+	z[0] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 25 */+	MONT_SQR_MUL(s0, s1, s2, a[2], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[2]);+	z[1] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 26 */+	MONT_SQR_MUL(s0, s1, s2, a[3], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[3]);+	z[2] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 27 */+	MONT_SQR_MUL(s0, s1, s2, a[4], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[4]);+	z[3] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 28 */+	MONT_SQR_MUL(s0, s1, s2, a[5], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[5]);+	z[4] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 29 */+	MONT_SQR_MUL(s0, s1, s2, a[6], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[6]);+	z[5] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 30 */+	MONT_SQR_MUL(s0, s1, s2, a[7], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[16]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[7]);+	z[6] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 31 */+	MONT_SQR_MUL(s0, s1, s2, a[8], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[16]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[8]);+	z[7] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 32 */+	MONT_SQR_MUL(s0, s1, s2, a[9], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[17]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[16], a[16]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[9]);+	z[8] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 33 */+	MONT_SQR_MUL(s0, s1, s2, a[10], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[17]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[10]);+	z[9] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 34 */+	MONT_SQR_MUL(s0, s1, s2, a[11], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[18]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[17], a[17]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[11]);+	z[10] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 35 */+	MONT_SQR_MUL(s0, s1, s2, a[12], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[18]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[12]);+	z[11] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 36 */+	MONT_SQR_MUL(s0, s1, s2, a[13], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[19]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[18], a[18]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[13]);+	z[12] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 37 */+	MONT_SQR_MUL(s0, s1, s2, a[14], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[19]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[14]);+	z[13] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 38 */+	MONT_SQR_MUL(s0, s1, s2, a[15], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[20]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[19], a[19]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[15]);+	z[14] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 39 */+	MONT_SQR_MUL(s0, s1, s2, a[16], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[20]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[16]);+	z[15] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 40 */+	MONT_SQR_MUL(s0, s1, s2, a[17], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[21]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[20], a[20]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[17]);+	z[16] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 41 */+	MONT_SQR_MUL(s0, s1, s2, a[18], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[21]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[18]);+	z[17] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 42 */+	MONT_SQR_MUL(s0, s1, s2, a[19], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[22]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[21], a[21]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[19]);+	z[18] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 43 */+	MONT_SQR_MUL(s0, s1, s2, a[20], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[22]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[20]);+	z[19] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 44 */+	MONT_SQR_MUL(s0, s1, s2, a[21], a[23]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[22], a[22]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[21]);+	z[20] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 45 */+	MONT_SQR_MUL(s0, s1, s2, a[22], a[23]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[22]);+	z[21] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 46 */+	MONT_SQR_MAC(t0, t1, t2, a[23], a[23]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[23]);+	z[22] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	z[23] = t0;++	/* under 2m, with t1 the bit above n limbs: at most one subtraction */+	borrow = sub_n(r, z, m, 24);+	take = t1 | (borrow ^ 1);+	select_n(r, r, z, take & 1, 24);+}++/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */+static void crypton_mont_sqr32(limb_t *r, const limb_t *a, const limb_t *m,+                               limb_t n0, limb_t *t)+{+	limb_t *u = t, *z = t + 32;+	limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;++	/* column 0 */+	MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);+	u[0] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 1 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);+	u[1] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 2 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);+	u[2] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 3 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);+	u[3] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 4 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);+	u[4] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 5 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);+	u[5] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 6 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);+	u[6] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 7 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);+	u[7] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 8 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);+	u[8] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 9 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);+	u[9] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 10 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);+	u[10] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 11 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);+	u[11] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 12 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);+	u[12] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 13 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);+	u[13] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 14 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);+	u[14] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 15 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);+	u[15] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 16 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);+	u[16] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[16], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 17 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[1]);+	u[17] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[17], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 18 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[1]);+	u[18] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[18], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 19 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[1]);+	u[19] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[19], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 20 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[1]);+	u[20] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[20], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 21 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[1]);+	u[21] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[21], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 22 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[1]);+	u[22] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[22], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 23 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[1]);+	u[23] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[23], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 24 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[1]);+	u[24] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[24], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 25 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[1]);+	u[25] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[25], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 26 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[1]);+	u[26] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[26], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 27 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[15]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[1]);+	u[27] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[27], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 28 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[1]);+	u[28] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[28], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 29 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[16]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[15]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[1]);+	u[29] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[29], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 30 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[16]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[1]);+	u[30] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[30], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 31 */+	MONT_SQR_MUL(s0, s1, s2, a[0], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[1], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[17]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[16]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[0], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[1]);+	u[31] = t0 * n0;+	MONT_SQR_MAC(t0, t1, t2, u[31], m[0]);+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 32 */+	MONT_SQR_MUL(s0, s1, s2, a[1], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[2], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[17]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[16], a[16]);+	MONT_SQR_MAC(t0, t1, t2, u[1], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[2]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[1]);+	z[0] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 33 */+	MONT_SQR_MUL(s0, s1, s2, a[2], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[3], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[18]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[17]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[2], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[3]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[2]);+	z[1] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 34 */+	MONT_SQR_MUL(s0, s1, s2, a[3], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[4], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[18]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[17], a[17]);+	MONT_SQR_MAC(t0, t1, t2, u[3], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[4]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[3]);+	z[2] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 35 */+	MONT_SQR_MUL(s0, s1, s2, a[4], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[5], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[19]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[18]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[4], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[5]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[4]);+	z[3] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 36 */+	MONT_SQR_MUL(s0, s1, s2, a[5], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[6], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[19]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[18], a[18]);+	MONT_SQR_MAC(t0, t1, t2, u[5], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[6]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[5]);+	z[4] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 37 */+	MONT_SQR_MUL(s0, s1, s2, a[6], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[7], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[20]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[19]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[6], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[7]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[6]);+	z[5] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 38 */+	MONT_SQR_MUL(s0, s1, s2, a[7], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[8], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[20]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[19], a[19]);+	MONT_SQR_MAC(t0, t1, t2, u[7], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[8]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[7]);+	z[6] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 39 */+	MONT_SQR_MUL(s0, s1, s2, a[8], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[9], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[21]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[20]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[8], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[9]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[8]);+	z[7] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 40 */+	MONT_SQR_MUL(s0, s1, s2, a[9], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[10], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[21]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[20], a[20]);+	MONT_SQR_MAC(t0, t1, t2, u[9], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[10]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[9]);+	z[8] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 41 */+	MONT_SQR_MUL(s0, s1, s2, a[10], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[11], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[22]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[21]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[10], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[11]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[10]);+	z[9] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 42 */+	MONT_SQR_MUL(s0, s1, s2, a[11], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[12], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[22]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[21], a[21]);+	MONT_SQR_MAC(t0, t1, t2, u[11], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[12]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[11]);+	z[10] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 43 */+	MONT_SQR_MUL(s0, s1, s2, a[12], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[13], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[23]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[22]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[12], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[13]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[12]);+	z[11] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 44 */+	MONT_SQR_MUL(s0, s1, s2, a[13], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[14], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[23]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[22], a[22]);+	MONT_SQR_MAC(t0, t1, t2, u[13], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[14]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[13]);+	z[12] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 45 */+	MONT_SQR_MUL(s0, s1, s2, a[14], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[15], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[24]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[23]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[14], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[15]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[14]);+	z[13] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 46 */+	MONT_SQR_MUL(s0, s1, s2, a[15], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[16], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[24]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[23], a[23]);+	MONT_SQR_MAC(t0, t1, t2, u[15], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[16]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[15]);+	z[14] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 47 */+	MONT_SQR_MUL(s0, s1, s2, a[16], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[17], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[25]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[24]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[16], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[17]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[16]);+	z[15] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 48 */+	MONT_SQR_MUL(s0, s1, s2, a[17], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[18], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[25]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[24], a[24]);+	MONT_SQR_MAC(t0, t1, t2, u[17], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[18]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[17]);+	z[16] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 49 */+	MONT_SQR_MUL(s0, s1, s2, a[18], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[19], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[26]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[25]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[18], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[19]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[18]);+	z[17] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 50 */+	MONT_SQR_MUL(s0, s1, s2, a[19], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[20], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[26]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[25], a[25]);+	MONT_SQR_MAC(t0, t1, t2, u[19], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[20]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[19]);+	z[18] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 51 */+	MONT_SQR_MUL(s0, s1, s2, a[20], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[21], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[27]);+	MONT_SQR_MAC(s0, s1, s2, a[25], a[26]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[20], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[21]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[20]);+	z[19] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 52 */+	MONT_SQR_MUL(s0, s1, s2, a[21], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[22], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[25], a[27]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[26], a[26]);+	MONT_SQR_MAC(t0, t1, t2, u[21], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[22]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[21]);+	z[20] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 53 */+	MONT_SQR_MUL(s0, s1, s2, a[22], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[23], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[25], a[28]);+	MONT_SQR_MAC(s0, s1, s2, a[26], a[27]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[22], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[23]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[22]);+	z[21] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 54 */+	MONT_SQR_MUL(s0, s1, s2, a[23], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[24], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[25], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[26], a[28]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[27], a[27]);+	MONT_SQR_MAC(t0, t1, t2, u[23], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[24]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[23]);+	z[22] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 55 */+	MONT_SQR_MUL(s0, s1, s2, a[24], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[25], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[26], a[29]);+	MONT_SQR_MAC(s0, s1, s2, a[27], a[28]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[24], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[25]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[24]);+	z[23] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 56 */+	MONT_SQR_MUL(s0, s1, s2, a[25], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[26], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[27], a[29]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[28], a[28]);+	MONT_SQR_MAC(t0, t1, t2, u[25], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[26]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[25]);+	z[24] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 57 */+	MONT_SQR_MUL(s0, s1, s2, a[26], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[27], a[30]);+	MONT_SQR_MAC(s0, s1, s2, a[28], a[29]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[26], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[27]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[26]);+	z[25] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 58 */+	MONT_SQR_MUL(s0, s1, s2, a[27], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[28], a[30]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[29], a[29]);+	MONT_SQR_MAC(t0, t1, t2, u[27], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[28]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[27]);+	z[26] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 59 */+	MONT_SQR_MUL(s0, s1, s2, a[28], a[31]);+	MONT_SQR_MAC(s0, s1, s2, a[29], a[30]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[28], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[29]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[28]);+	z[27] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 60 */+	MONT_SQR_MUL(s0, s1, s2, a[29], a[31]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, a[30], a[30]);+	MONT_SQR_MAC(t0, t1, t2, u[29], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[30]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[29]);+	z[28] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 61 */+	MONT_SQR_MUL(s0, s1, s2, a[30], a[31]);+	MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);+	MONT_SQR_MAC(t0, t1, t2, u[30], m[31]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[30]);+	z[29] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	/* column 62 */+	MONT_SQR_MAC(t0, t1, t2, a[31], a[31]);+	MONT_SQR_MAC(t0, t1, t2, u[31], m[31]);+	z[30] = t0;+	t0 = t1;+	t1 = t2;+	t2 = 0;+	z[31] = t0;++	/* under 2m, with t1 the bit above n limbs: at most one subtraction */+	borrow = sub_n(r, z, m, 32);+	take = t1 | (borrow ^ 1);+	select_n(r, r, z, take & 1, 32);+}++#endif
+ cbits/crypton_mont_sqr.py view
@@ -0,0 +1,117 @@+#!/usr/bin/env python3+"""Generate cbits/crypton_mont_sqr.h: Montgomery squaring for AArch64 at the+limb counts of RSA's CRT halves, fully unrolled and product-scanning.++Usage: python3 cbits/crypton_mont_sqr.py > cbits/crypton_mont_sqr.h++The result is a column at a time, with the reduction folded into the same+scan (the FIPS method), so the running sum stays in three registers instead+of going through memory a row at a time.  Each product off the diagonal is+summed once into a column of its own, doubled, and added in.+"""++SIZES = (16, 24, 32)++HEADER = """\+/* Generated by cbits/crypton_mont_sqr.py; do not edit.+ *+ * Montgomery squaring for AArch64 at 16, 24 and 32 limbs, the halves of+ * RSA-2048, -3072 and -4096.  Each answers what mont_sqr answers. */+#ifndef CRYPTON_MONT_SQR_H+#define CRYPTON_MONT_SQR_H++#include "crypton_bignum.h"++/* (t2:t1:t0) += x * y */+#define MONT_SQR_MAC(t0, t1, t2, x, y)                                  \\+	do {                                                                \\+		limb_t lo_, hi_;                                                \\+		__asm__("mul\\t%0, %5, %6\\n\\t"                                   \\+		        "umulh\\t%1, %5, %6\\n\\t"                                 \\+		        "adds\\t%2, %2, %0\\n\\t"                                  \\+		        "adcs\\t%3, %3, %1\\n\\t"                                  \\+		        "adc\\t%4, %4, xzr"                                       \\+		        : "=&r"(lo_), "=&r"(hi_), "+r"(t0), "+r"(t1), "+r"(t2)  \\+		        : "r"(x), "r"(y)                                        \\+		        : "cc");                                                \\+	} while (0)++/* (s2:s1:s0) = x * y */+#define MONT_SQR_MUL(s0, s1, s2, x, y)                                  \\+	__asm__("mul\\t%0, %3, %4\\n\\t"                                       \\+	        "umulh\\t%1, %3, %4\\n\\t"                                     \\+	        "mov\\t%2, xzr"                                               \\+	        : "=&r"(s0), "=&r"(s1), "=r"(s2)                            \\+	        : "r"(x), "r"(y))++/* (t2:t1:t0) += 2 * (s2:s1:s0) */+#define MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2)                           \\+	do {                                                                \\+		s2 = (s2 << 1) | (s1 >> 63);                                    \\+		s1 = (s1 << 1) | (s0 >> 63);                                    \\+		s0 <<= 1;                                                       \\+		__asm__("adds\\t%0, %0, %3\\n\\t"                                  \\+		        "adcs\\t%1, %1, %4\\n\\t"                                  \\+		        "adc\\t%2, %2, %5"                                        \\+		        : "+r"(t0), "+r"(t1), "+r"(t2)                          \\+		        : "r"(s0), "r"(s1), "r"(s2)                             \\+		        : "cc");                                                \\+	} while (0)+"""++FOOTER = """\+#endif+"""+++def gen(n):+    out = []+    w = out.append+    w(f"/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */")+    w(f"static void crypton_mont_sqr{n}(limb_t *r, const limb_t *a, const limb_t *m,")+    w(f"{' ' * len(f'static void crypton_mont_sqr{n}(')}limb_t n0, limb_t *t)")+    w("{")+    w(f"\tlimb_t *u = t, *z = t + {n};")+    w("\tlimb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;")+    w("")+    for i in range(2 * n - 1):+        w(f"\t/* column {i} */")+        pairs = [(j, i - j) for j in range(max(0, i - n + 1), n) if j < i - j]+        if pairs:+            j, k = pairs[0]+            w(f"\tMONT_SQR_MUL(s0, s1, s2, a[{j}], a[{k}]);")+            for (j, k) in pairs[1:]:+                w(f"\tMONT_SQR_MAC(s0, s1, s2, a[{j}], a[{k}]);")+            w("\tMONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);")+        if i % 2 == 0:+            w(f"\tMONT_SQR_MAC(t0, t1, t2, a[{i // 2}], a[{i // 2}]);")+        for j in range(max(0, i - n + 1), min(i, n)):+            w(f"\tMONT_SQR_MAC(t0, t1, t2, u[{j}], m[{i - j}]);")+        if i < n:+            w(f"\tu[{i}] = t0 * n0;")+            w(f"\tMONT_SQR_MAC(t0, t1, t2, u[{i}], m[0]);")+        else:+            w(f"\tz[{i - n}] = t0;")+        w("\tt0 = t1;")+        w("\tt1 = t2;")+        w("\tt2 = 0;")+    w(f"\tz[{n - 1}] = t0;")+    w("")+    w("\t/* under 2m, with t1 the bit above n limbs: at most one subtraction */")+    w(f"\tborrow = sub_n(r, z, m, {n});")+    w("\ttake = t1 | (borrow ^ 1);")+    w(f"\tselect_n(r, r, z, take & 1, {n});")+    w("}")+    w("")+    return "\n".join(out)+++def main():+    print(HEADER)+    for n in SIZES:+        print(gen(n))+    print(FOOTER, end="")+++if __name__ == "__main__":+    main()
cbits/crypton_powm.c view
@@ -22,6 +22,15 @@ #include <crypton_powm.h> #include <crypton_bzero.h> +/* On AArch64, squaring at the RSA half sizes goes through generated code+ * that scans a column at a time with the reduction folded in; see+ * cbits/crypton_mont_sqr.py.  CRYPTON_NO_MONT_SQR keeps mont_sqr, to compare. */+#if defined(__aarch64__) && LIMB_BITS == 64 && !defined(CRYPTON_NO_MONT_SQR) \+    && (defined(__GNUC__) || defined(__clang__))+#define CRYPTON_MONT_SQR 1+#include <crypton_mont_sqr.h>+#endif+ /*  * At RSA sizes on x86-64, the Montgomery multiplication below is the whole  * cost, and s2n-bignum's is twice as fast because the C cannot form the two@@ -180,6 +189,13 @@ #else 	(void)scratch; 	(void)s2n;+#endif+#ifdef CRYPTON_MONT_SQR+	switch (n) {+	case 16: crypton_mont_sqr16(r, a, m, n0, t); return;+	case 24: crypton_mont_sqr24(r, a, m, n0, t); return;+	case 32: crypton_mont_sqr32(r, a, m, n0, t); return;+	} #endif 	mont_sqr(r, a, m, n0, n, t); }
+ cbits/s2n/x86_att/_internal_s2n_bignum_x86_att.h view
@@ -0,0 +1,33 @@+/*+ * crypton's, not s2n-bignum's: what the vendored assembly needs on Windows,+ * kept out of the vendored files so that import.sh can replace them as it+ * always has.+ *+ * Every file in this directory includes "_internal_s2n_bignum_x86_att.h",+ * and a quoted include looks first in the directory of the file that asks+ * for it -- so this is the one each of them gets, and it hands on to+ * upstream's own in cbits/s2n/include.  On Linux and macOS it changes+ * nothing.+ *+ * On Windows, two things.  The ELF directives .type and .size are refused by+ * the COFF assemblers -- gcc's says "junk at end of line" and clang's+ * "expected absolute expression" -- and there is nothing in a PE object for+ * them to say, so they are emptied, as upstream does for Mach-O.  And the+ * calling convention is Microsoft's, not System V's: each file carries a+ * prologue that moves its arguments into the registers it was written+ * for, under WINDOWS_ABI, which upstream leaves to the build to define.+ */+/* By a path from this file rather than by #include_next: clang, finding+ * this file next to the one that asked for it, starts #include_next from+ * the top of the search and finds this file again, without end. */+#include "../include/_internal_s2n_bignum_x86_att.h"++#if defined(_WIN32)+#  undef S2N_BN_FUNCTION_TYPE_DIRECTIVE+#  define S2N_BN_FUNCTION_TYPE_DIRECTIVE(name) /* not used in COFF */+#  undef S2N_BN_SIZE_DIRECTIVE+#  define S2N_BN_SIZE_DIRECTIVE(name) /* not used in COFF */+#  ifndef WINDOWS_ABI+#    define WINDOWS_ABI 1+#  endif+#endif
cbits/tests/ct/run.sh view
@@ -309,6 +309,13 @@ 		echo "     multiplication cannot run here" 	fi 	;;+aarch64 | arm64)+	# the generated squaring is separate code at each size; 2048 is above+	for bytes in 128 192; do+		run_one "powm_$((bytes * 8))" "cbits/crypton_powm.c" \+			"-DCT_POWM_BYTES=$bytes" powm+	done+	;; esac run_one p256    "cbits/p256/p256.c cbits/p256/p256_ec.c" "" run_one x25519  "cbits/curve25519/curve25519-donna-c64.c" ""
crypton.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               crypton-version:            2.2.2+version:            2.2.3 -- crypton's own code is BSD-3-Clause.  The parts of -- cbits/aes/gcm_fused_x86.c that follow picotls's fusion are MIT, and the -- vendored s2n-bignum assembly in cbits/s2n is taken under ISC, and the@@ -69,6 +69,7 @@     cbits/blake2/ref/*.h     cbits/blake2/sse/*.h     cbits/crypton_hash_prefix.c+    cbits/crypton_mont_sqr.py     cbits/mlkem/*.S     cbits/mlkem/*.c     cbits/mlkem/*.h@@ -151,6 +152,7 @@     cbits/s2n/import.sh     cbits/s2n/include/*.h     cbits/s2n/x86_att/*.S+    cbits/s2n/x86_att/*.h     cbits/bearssl/README.md     cbits/bearssl/VERSION     cbits/bearssl/import.sh