packages feed

crypton-2.2.3: cbits/crypton_mont_sqr.h

/* 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