diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
 # CHANGELOG for crypton
 
+## 2.2.5
+
+**RSA private-key operations check their CRT result.**  A fault in one
+half of the computation could hand out a signature that reveals a prime of
+the key; the result is now raised back to the public exponent first, as
+OpenSSL does, at a cost of two or three per cent on signing.
+
+* perf(rsa): verification in C at every RSA size on Apple AArch64
+  [#340](https://github.com/kazu-yamamoto/crypton/pull/340)
+* perf(rsa): a generated squaring at 48 limbs on AArch64
+  [#341](https://github.com/kazu-yamamoto/crypton/pull/341)
+* perf(rsa): verification without lists or Integer round trips
+  [#342](https://github.com/kazu-yamamoto/crypton/pull/342)
+* ci: time out instead of waiting on a stalled package mirror
+  [#343](https://github.com/kazu-yamamoto/crypton/pull/343)
+* fix(rsa): check the CRT result before letting it out
+  [#344](https://github.com/kazu-yamamoto/crypton/pull/344)
+* perf(hash): one context for a one-shot hash and for MGF1
+  [#345](https://github.com/kazu-yamamoto/crypton/pull/345)
+* perf(rsa): RSA-3072's 24-limb square from 8-limb pieces on x86-64
+  [#346](https://github.com/kazu-yamamoto/crypton/pull/346)
+
 ## 2.2.4
 
 **New module `Crypto.PubKey.RSA.Blinded`.**  A `BlindedKey` carries RSA
diff --git a/Crypto/Hash.hs b/Crypto/Hash.hs
--- a/Crypto/Hash.hs
+++ b/Crypto/Hash.hs
@@ -53,12 +53,20 @@
 import qualified Crypto.Internal.ByteArray as B
 import qualified Data.ByteString.Lazy as L
 import Data.Int (Int32)
+import Data.Word (Word8)
+import Foreign.Marshal.Alloc (allocaBytes)
 import qualified Foreign.Marshal.Utils as FMU
 import Foreign.Ptr (Ptr, castPtr, plusPtr)
 
 -- | Hash a strict bytestring into a digest.
-hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
-hash bs = hashFinalize $ hashUpdate hashInit bs
+hash :: forall ba a. (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
+hash bs = Digest $
+    allocAndFreezePrim (hashDigestSize (undefined :: a)) $ \(dig :: Ptr (Digest a)) ->
+        -- one context, used in place: the pure steps would copy it three times
+        allocaBytes (hashInternalContextSize (undefined :: a)) $ \(ctx :: Ptr (Context a)) -> do
+            hashInternalInit ctx
+            B.withByteArray bs (updateBlocks ctx (B.length bs))
+            hashInternalFinalize ctx dig
 
 -- | Hash the first N bytes of a bytestring, with code path independent from N.
 hashPrefix
@@ -92,20 +100,19 @@
 hashUpdates c l
     | null ls = c
     | otherwise = Context $ B.copyAndFreeze c $ \(ctx :: Ptr (Context a)) ->
-        mapM_ (\b -> B.withByteArray b (processBlocks ctx (B.length b))) ls
+        mapM_ (\b -> B.withByteArray b (updateBlocks ctx (B.length b))) ls
   where
     ls = filter (not . B.null) l
-    -- process the data in 2GB chunks to fit in uint32_t and Int on 32 bit systems
-    processBlocks ctx bytesLeft dataPtr
-        | bytesLeft == 0 = return ()
-        | otherwise = do
-            hashInternalUpdate ctx dataPtr (fromIntegral actuallyProcessed)
-            processBlocks
-                ctx
-                (bytesLeft - actuallyProcessed)
-                (dataPtr `plusPtr` actuallyProcessed)
-      where
-        actuallyProcessed = min bytesLeft (fromIntegral (maxBound :: Int32))
+
+-- | Process the data in 2GB chunks to fit in uint32_t and Int on 32 bit systems
+updateBlocks :: HashAlgorithm a => Ptr (Context a) -> Int -> Ptr Word8 -> IO ()
+updateBlocks ctx bytesLeft dataPtr
+    | bytesLeft == 0 = return ()
+    | otherwise = do
+        hashInternalUpdate ctx dataPtr (fromIntegral actuallyProcessed)
+        updateBlocks ctx (bytesLeft - actuallyProcessed) (dataPtr `plusPtr` actuallyProcessed)
+  where
+    actuallyProcessed = min bytesLeft (fromIntegral (maxBound :: Int32))
 
 -- | Finalize a context and return a digest.
 hashFinalize
diff --git a/Crypto/Number/ModArithmetic.hs b/Crypto/Number/ModArithmetic.hs
--- a/Crypto/Number/ModArithmetic.hs
+++ b/Crypto/Number/ModArithmetic.hs
@@ -43,15 +43,13 @@
 import Crypto.Internal.Compat (unsafeDoIO)
 import Crypto.Number.Basic
 import Crypto.Number.Compat
+import Crypto.Number.ModArithmetic.Pub (expPub)
 import qualified Crypto.Number.Serialize.Internal as Internal
 import Data.Memory.PtrMethods (memSet)
 import Data.Word (Word32, Word8)
 import Foreign.C.Types (CInt (..))
 import Foreign.Marshal.Alloc (allocaBytes)
 import Foreign.Ptr (Ptr, plusPtr)
-import Data.IORef (IORef, atomicModifyIORef', newIORef)
-import System.IO.Unsafe (unsafePerformIO)
-import Crypto.Internal.ByteArray (Bytes, allocRet, withByteArray)
 
 -- | Raised when two numbers are supposed to be coprimes but are not.
 data CoprimesAssertionError = CoprimesAssertionError
@@ -186,87 +184,6 @@
     | otherwise = slow
   where
     slow = gmpPowModInteger b e m `onGmpUnsupported` exponentiation b e m
-
--- | The windowless exponentiation in C, for an exponent that is not a
---   secret.  'Nothing' when the C declines, which it does on every machine
---   where what the caller already has is faster -- so this is an
---   optimisation and never the only path.  The base has to be reduced and
---   the exponent positive, which the guard above sees to.
-expPub :: Integer -> Integer -> Integer -> Maybe Integer
-expPub b e m = unsafeDoIO $ do
-    known <- r2For m
-    case known of
-        Nothing -> return Nothing
-        Just r2 ->
-            allocaBytes (sum widths) $ \start -> case scanl plusPtr start widths of
-                (out : base : expo : modu : _) -> do
-                    _ <- Internal.i2ospOf b base mLen
-                    _ <- Internal.i2ospOf e expo eLen
-                    _ <- Internal.i2ospOf m modu mLen
-                    r <- withByteArray r2 $ \pr2 ->
-                        c_powm_pub_r2
-                            out
-                            base
-                            (fromIntegral mLen)
-                            expo
-                            (fromIntegral eLen)
-                            modu
-                            (fromIntegral mLen)
-                            pr2
-                    if r == 0
-                        then do
-                            !v <- Internal.os2ip out mLen
-                            return (Just v)
-                        else return Nothing
-                _ -> return Nothing
-  where
-    !mLen = numBytes m
-    !eLen = numBytes e
-    widths = [mLen, mLen, eLen, mLen]
-
--- | R^2 mod m for the public path, kept for the last few moduli, since a
--- program verifies under the same keys again and again.  'Nothing' is kept
--- too: it means the C declines this modulus, which is then not asked again.
-r2For :: Integer -> IO (Maybe Bytes)
-r2For m = do
-    found <- atomicModifyIORef' r2Table $ \ks -> case break ((== m) . fst) ks of
-        (before, hit : after) -> (hit : before ++ after, Just (snd hit))
-        _ -> (ks, Nothing)
-    case found of
-        Just r2 -> return r2
-        Nothing -> do
-            let mLen = numBytes m
-            r2 <- allocaBytes mLen $ \modu -> do
-                _ <- Internal.i2ospOf m modu mLen
-                (r, out) <- allocRet mLen $ \pout -> c_powm_r2 pout modu (fromIntegral mLen)
-                return (if r == 0 then Just out else Nothing)
-            atomicModifyIORef' r2Table $ \ks -> (take r2TableSize ((m, r2) : ks), ())
-            return r2
-
-r2TableSize :: Int
-r2TableSize = 8
-
-r2Table :: IORef [(Integer, Maybe Bytes)]
-r2Table = unsafePerformIO (newIORef [])
-{-# NOINLINE r2Table #-}
-
--- safe, as the secure one below is: the call is tens of microseconds at RSA
--- sizes, and the hundred nanoseconds this costs over an unsafe call is
--- nothing beside holding a capability for that long in a server
-foreign import ccall safe "crypton_powm_pub_r2"
-    c_powm_pub_r2
-        :: Ptr Word8
-        -> Ptr Word8
-        -> Word32
-        -> Ptr Word8
-        -> Word32
-        -> Ptr Word8
-        -> Word32
-        -> Ptr Word8
-        -> IO CInt
-
-foreign import ccall unsafe "crypton_powm_r2"
-    c_powm_r2 :: Ptr Word8 -> Ptr Word8 -> Word32 -> IO CInt
 
 -- | @exponentiation@ computes modular exponentiation as /b^e mod m/
 -- using repetitive squaring.
diff --git a/Crypto/Number/ModArithmetic/Pub.hs b/Crypto/Number/ModArithmetic/Pub.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Number/ModArithmetic/Pub.hs
@@ -0,0 +1,158 @@
+{-# LANGUAGE BangPatterns #-}
+
+-- |
+-- Module      : Crypto.Number.ModArithmetic.Pub
+-- License     : BSD-style
+-- Stability   : experimental
+-- Portability : Good
+--
+-- The C exponentiation for an exponent that is not a secret, and the R^2
+-- it keeps per modulus.  Internal: 'expPub' is behind 'expFast', and
+-- 'expPubBytes' behind RSA's public-key operation.
+module Crypto.Number.ModArithmetic.Pub (
+    expPub,
+    expPubBytes,
+) where
+
+import Crypto.Internal.ByteArray (
+    ByteArray,
+    ByteArrayAccess,
+    Bytes,
+    allocRet,
+    withByteArray,
+ )
+import qualified Crypto.Internal.ByteArray as B
+import Crypto.Internal.Compat (unsafeDoIO)
+import Crypto.Number.Basic
+import qualified Crypto.Number.Serialize.Internal as Internal
+import Data.IORef (IORef, atomicModifyIORef', newIORef)
+import Data.Word (Word32, Word8)
+import Foreign.C.Types (CInt (..))
+import Foreign.Marshal.Alloc (allocaBytes)
+import Foreign.Ptr (Ptr, plusPtr)
+import System.IO.Unsafe (unsafePerformIO)
+
+-- | The windowless exponentiation in C, for an exponent that is not a
+--   secret.  'Nothing' when the C declines, which it does on every machine
+--   where what the caller already has is faster -- so this is an
+--   optimisation and never the only path.  The base has to be reduced and
+--   the exponent positive, which the caller sees to.
+expPub :: Integer -> Integer -> Integer -> Maybe Integer
+expPub b e m = unsafeDoIO $ do
+    known <- r2For m
+    case known of
+        Nothing -> return Nothing
+        Just (r2, modu) ->
+            allocaBytes (sum widths) $ \start -> case scanl plusPtr start widths of
+                (out : base : expo : _) -> do
+                    _ <- Internal.i2ospOf b base mLen
+                    _ <- Internal.i2ospOf e expo eLen
+                    r <- withByteArray modu $ \pm -> withByteArray r2 $ \pr2 ->
+                        c_powm_pub_r2
+                            out
+                            base
+                            (fromIntegral mLen)
+                            expo
+                            (fromIntegral eLen)
+                            pm
+                            (fromIntegral mLen)
+                            pr2
+                    if r == 0
+                        then do
+                            !v <- Internal.os2ip out mLen
+                            return (Just v)
+                        else return Nothing
+                _ -> return Nothing
+  where
+    !mLen = numBytes m
+    !eLen = numBytes e
+    widths = [mLen, mLen, eLen]
+
+-- | The same with the base and the answer as big-endian bytes, as long as
+--   the modulus: what RSA verification has in hand, so neither goes through
+--   an 'Integer'.  'Nothing' also when the base is not below the modulus.
+expPubBytes
+    :: (ByteArrayAccess bi, ByteArray bo) => Integer -> Integer -> bi -> Maybe bo
+expPubBytes e m b
+    | e <= 0 || m <= 1 || even m || B.length b /= mLen = Nothing
+    | otherwise = unsafeDoIO $ do
+        known <- r2For m
+        case known of
+            Nothing -> return Nothing
+            Just (r2, modu)
+                | not (below b modu) -> return Nothing
+                | otherwise -> allocaBytes eLen $ \expo -> do
+                    _ <- Internal.i2ospOf e expo eLen
+                    (r, out) <- allocRet mLen $ \pout ->
+                        withByteArray b $ \pb -> withByteArray modu $ \pm ->
+                            withByteArray r2 $ \pr2 ->
+                                c_powm_pub_r2
+                                    pout
+                                    pb
+                                    (fromIntegral mLen)
+                                    expo
+                                    (fromIntegral eLen)
+                                    pm
+                                    (fromIntegral mLen)
+                                    pr2
+                    return (if r == 0 then Just out else Nothing)
+  where
+    !mLen = numBytes m
+    !eLen = numBytes e
+
+-- big-endian numbers of one length: the first byte that differs decides
+below :: (ByteArrayAccess a, ByteArrayAccess b) => a -> b -> Bool
+below x y = go 0
+  where
+    n = B.length x
+    go i
+        | i >= n = False
+        | otherwise = case compare (B.index x i) (B.index y i) of
+            EQ -> go (i + 1)
+            o -> o == LT
+
+-- | R^2 mod m for the public path, and m in bytes, kept for the last few
+-- moduli, since a program verifies under the same keys again and again.
+-- 'Nothing' is kept too: it means the C declines this modulus, which is
+-- then not asked again.
+r2For :: Integer -> IO (Maybe (Bytes, Bytes))
+r2For m = do
+    found <- atomicModifyIORef' r2Table $ \ks -> case break ((== m) . fst) ks of
+        (before, hit : after) -> (hit : before ++ after, Just (snd hit))
+        _ -> (ks, Nothing)
+    case found of
+        Just r2 -> return r2
+        Nothing -> do
+            let mLen = numBytes m
+            (r2, modu) <- allocRet mLen $ \modu -> do
+                _ <- Internal.i2ospOf m modu mLen
+                (r, out) <- allocRet mLen $ \pout -> c_powm_r2 pout modu (fromIntegral mLen)
+                return (if r == 0 then Just out else Nothing)
+            let kept = fmap (\x -> (x, modu)) r2
+            atomicModifyIORef' r2Table $ \ks -> (take r2TableSize ((m, kept) : ks), ())
+            return kept
+
+r2TableSize :: Int
+r2TableSize = 8
+
+r2Table :: IORef [(Integer, Maybe (Bytes, Bytes))]
+r2Table = unsafePerformIO (newIORef [])
+{-# NOINLINE r2Table #-}
+
+-- safe, as the secure one is: the call is tens of microseconds at RSA
+-- sizes, and the hundred nanoseconds this costs over an unsafe call is
+-- nothing beside holding a capability for that long in a server
+foreign import ccall safe "crypton_powm_pub_r2"
+    c_powm_pub_r2
+        :: Ptr Word8
+        -> Ptr Word8
+        -> Word32
+        -> Ptr Word8
+        -> Word32
+        -> Ptr Word8
+        -> Word32
+        -> Ptr Word8
+        -> IO CInt
+
+foreign import ccall unsafe "crypton_powm_r2"
+    c_powm_r2 :: Ptr Word8 -> Ptr Word8 -> Word32 -> IO CInt
diff --git a/Crypto/PubKey/MaskGenFunction.hs b/Crypto/PubKey/MaskGenFunction.hs
--- a/Crypto/PubKey/MaskGenFunction.hs
+++ b/Crypto/PubKey/MaskGenFunction.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 -- |
 -- Module      : Crypto.PubKey.MaskGenFunction
@@ -11,10 +11,17 @@
     mgf1,
 ) where
 
-import Crypto.Hash
-import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, Bytes)
+import Control.Monad (forM_)
+import Crypto.Hash (Context, Digest)
+import Crypto.Hash.IO (HashAlgorithm (..))
+import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess)
 import qualified Crypto.Internal.ByteArray as B
-import Crypto.Number.Serialize (i2ospOf_)
+import Data.Bits (shiftR)
+import Data.Word (Word8)
+import Foreign.Marshal.Alloc (allocaBytes)
+import Foreign.Marshal.Utils (copyBytes)
+import Foreign.Ptr (Ptr, castPtr, plusPtr)
+import Foreign.Storable (pokeByteOff)
 
 -- | Represent a mask generation algorithm
 type MaskGenAlgorithm seed output =
@@ -26,20 +33,33 @@
 
 -- | Mask generation algorithm MGF1
 mgf1
-    :: (ByteArrayAccess seed, ByteArray output, HashAlgorithm hashAlg)
+    :: forall seed output hashAlg
+     . (ByteArrayAccess seed, ByteArray output, HashAlgorithm hashAlg)
     => hashAlg
     -> seed
     -> Int
     -> output
-mgf1 hashAlg seed len =
-    let !seededCtx = hashUpdate (hashInitWith hashAlg) seed
-     in B.take len $
-            B.concat $
-                map (hashCounter seededCtx) [0 .. fromIntegral (maxCounter - 1)]
+mgf1 hashAlg seed len
+    | len <= 0 = B.empty
+    | otherwise = B.allocAndFreeze len $ \out ->
+        -- the seeded context is kept, and copied for each block rather than
+        -- rebuilt; each block's digest is written straight into the output
+        allocaBytes ctxSize $ \(seeded :: Ptr (Context hashAlg)) ->
+            allocaBytes ctxSize $ \(ctx :: Ptr (Context hashAlg)) ->
+                allocaBytes digestLen $ \(dig :: Ptr (Digest hashAlg)) ->
+                    allocaBytes 4 $ \(cnt :: Ptr Word8) -> do
+                        hashInternalInit seeded
+                        B.withByteArray seed $ \p ->
+                            hashInternalUpdate seeded p (fromIntegral (B.length seed))
+                        forM_ [0 .. maxCounter - 1] $ \i -> do
+                            copyBytes ctx seeded ctxSize
+                            forM_ [0 .. 3] $ \k ->
+                                pokeByteOff cnt k (fromIntegral (i `shiftR` (8 * (3 - k))) :: Word8)
+                            hashInternalUpdate ctx cnt 4
+                            hashInternalFinalize ctx dig
+                            let off = i * digestLen
+                            copyBytes (out `plusPtr` off) (castPtr dig) (min digestLen (len - off))
   where
+    ctxSize = hashInternalContextSize hashAlg
     digestLen = hashDigestSize hashAlg
-    (chunks, left) = len `divMod` digestLen
-    maxCounter = if left > 0 then chunks + 1 else chunks
-
-    hashCounter :: HashAlgorithm a => Context a -> Integer -> Digest a
-    hashCounter ctx counter = hashFinalize $ hashUpdate ctx (i2ospOf_ 4 counter :: Bytes)
+    maxCounter = (len + digestLen - 1) `div` digestLen
diff --git a/Crypto/PubKey/RSA/PKCS15.hs b/Crypto/PubKey/RSA/PKCS15.hs
--- a/Crypto/PubKey/RSA/PKCS15.hs
+++ b/Crypto/PubKey/RSA/PKCS15.hs
@@ -415,10 +415,10 @@
     :: ByteArray signature => Int -> signature -> Either Error signature
 padSignature klen signature
     | klen < siglen + 11 = Left SignatureTooLong
-    | otherwise = Right (B.pack padding `B.append` signature)
+    | otherwise =
+        Right (B.concat [B.pack [0, 1], B.replicate (klen - siglen - 3) 0xff, B.pack [0], signature])
   where
     siglen = B.length signature
-    padding = 0 : 1 : (replicate (klen - siglen - 3) 0xff ++ [0])
 
 -- | Try to remove a standard PKCS1.5 encryption padding.
 --
diff --git a/Crypto/PubKey/RSA/PSS.hs b/Crypto/PubKey/RSA/PSS.hs
--- a/Crypto/PubKey/RSA/PSS.hs
+++ b/Crypto/PubKey/RSA/PSS.hs
@@ -30,11 +30,11 @@
 import Crypto.PubKey.RSA.Prim
 import Crypto.PubKey.RSA.Types
 import Crypto.Random.Types
-import Data.Bits (complement, shiftR, xor, (.&.))
+import Data.Bits (complement, shiftR, (.&.))
 import Data.Word
 
 import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess)
-import qualified Crypto.Internal.ByteArray as B (convert, eq)
+import qualified Crypto.Internal.ByteArray as B (bxor, convert, eq)
 
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
@@ -113,7 +113,7 @@
     h = B.convert $ hashWith (pssHash params) m'
     db = B.concat [B.replicate (dbLen - saltLen - 1) 0, B.singleton 1, salt]
     dbmask = pssMaskGenAlg params h dbLen
-    maskedDB = B.pack $ normalizeToKeySize pubBits $ B.zipWith xor db dbmask
+    maskedDB = normalizeToKeySize pubBits (B.bxor db dbmask :: ByteString)
     em = B.concat [maskedDB, h, B.singleton (pssTrailerField params)]
 
 -- | Sign using the PSS parameters and the salt explicitely passed as parameters.
@@ -303,7 +303,7 @@
     maskedDB = B.take dbLen em
     h = B.take hashLen $ B.drop (B.length maskedDB) em
     dbmask = pssMaskGenAlg params h dbLen
-    db = B.pack $ normalizeToKeySize pubBits $ B.zipWith xor maskedDB dbmask
+    db = normalizeToKeySize pubBits (B.bxor maskedDB dbmask :: ByteString)
     (ps0, z) = B.break (== 1) db
     (b1, salt) = B.splitAt 1 z
     m' = B.concat [B.replicate 8 0, mHash, salt]
@@ -313,9 +313,10 @@
 emTruncate :: Int -> Bool
 emTruncate bits = ((bits - 1) .&. 0x7) == 0
 
-normalizeToKeySize :: Int -> [Word8] -> [Word8]
-normalizeToKeySize _ [] = [] -- very unlikely
-normalizeToKeySize bits (x : xs) = x .&. normalizeMask bits : xs
+normalizeToKeySize :: Int -> ByteString -> ByteString
+normalizeToKeySize bits x = case B.uncons x of
+    Nothing -> x -- very unlikely
+    Just (h, t) -> B.cons (h .&. normalizeMask bits) t
 
 -- | The bits of the leftmost octet that belong to the encoding: the low
 -- @emBits `mod` 8@ of them, or all eight when that is zero.  Its complement
diff --git a/Crypto/PubKey/RSA/Prim.hs b/Crypto/PubKey/RSA/Prim.hs
--- a/Crypto/PubKey/RSA/Prim.hs
+++ b/Crypto/PubKey/RSA/Prim.hs
@@ -24,6 +24,7 @@
 import Crypto.Internal.Compat (unsafeDoIO)
 import Crypto.Number.Basic (numBytes)
 import Crypto.Number.ModArithmetic (expFast, expSafe)
+import Crypto.Number.ModArithmetic.Pub (expPubBytes)
 import Crypto.Number.Serialize (i2ospOf_, os2ip)
 import qualified Crypto.Number.Serialize.Internal as Internal
 import Crypto.PubKey.RSA.Types
@@ -40,7 +41,7 @@
 dpFast (Blinder r rm1) pk c =
     i2ospOf_
         (private_size pk)
-        (multiplication rm1 (m2 + h * (private_q pk)) (private_n pk))
+        (multiplication rm1 (crtChecked pk iC (m2 + h * (private_q pk))) (private_n pk))
   where
     re = expFast r (public_e $ private_pub pk) (private_n pk)
     iC = multiplication re (os2ip c) (private_n pk)
@@ -48,12 +49,23 @@
     h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk)
 
 dpFastNoBlinder :: ByteArray ba => PrivateKey -> ba -> ba
-dpFastNoBlinder pk c = i2ospOf_ (private_size pk) (m2 + h * (private_q pk))
+dpFastNoBlinder pk c = i2ospOf_ (private_size pk) (crtChecked pk iC (m2 + h * (private_q pk)))
   where
     iC = os2ip c
     (m1, m2) = crtHalves iC pk
     h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk)
 
+-- | The CRT answer m for c, raised back to e before it is let out: a fault
+-- in one half gives an m whose gcd with n is the other prime (Boneh, DeMillo
+-- and Lipton).  On a mismatch it is computed again without CRT, as OpenSSL does.
+crtChecked :: PrivateKey -> Integer -> Integer -> Integer
+crtChecked pk c m
+    | expFast m (public_e (private_pub pk)) n == c `mod` n = m
+    | private_d pk > 0 = expSafe c (private_d pk) n
+    | otherwise = m
+  where
+    n = private_n pk
+
 -- | c^dP mod p and c^dQ mod q, the halves of the private-key operation: both
 -- at once where the C can (AVX-512 IFMA, and the sizes of RSA-2048, -3072 and
 -- -4096), one after the other where it declines.
@@ -112,7 +124,9 @@
 
 -- | Compute the RSA encrypt primitive
 ep :: ByteArray ba => PublicKey -> ba -> ba
-ep pk m = i2ospOf_ (public_size pk) $ expFast (os2ip m) (public_e pk) (public_n pk)
+ep pk m = case expPubBytes (public_e pk) (public_n pk) m of
+    Just r -> r
+    Nothing -> i2ospOf_ (public_size pk) $ expFast (os2ip m) (public_e pk) (public_n pk)
 
 -- | multiply 2 integers in Zm only performing the modulo operation if necessary
 multiplication :: Integer -> Integer -> Integer -> Integer
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -78,10 +78,14 @@
 ones to reach for.  Pass `Nothing` only where the input is not attacker
 controlled and you have decided that it is not.
 
-The RSA rows in the tables below are the unblinded path.  A blinder costs one
-more exponentiation, by the public exponent, which is the cheap direction:
-measured on the M4, signing goes from about 460 to about 476 microseconds,
-under four per cent.
+The RSA rows in the tables below are the unblinded path.  A fresh blinder
+costs one more exponentiation, by the public exponent, which is the cheap
+direction: measured on the M4, signing goes from about 316 to about 331
+microseconds, under five per cent.  `signSafer` and `decryptSafer` pay less
+than that from 2.2.4: they keep the blinder of a key they have seen and
+square it for the next use, as OpenSSL does, drawing a fresh one every 32
+uses.  `Crypto.PubKey.RSA.Blinded` gives a caller the same thing to hold, a
+`BlindedKey` passed along from one operation to the next.
 
 Performance
 -----------
@@ -111,33 +115,33 @@
 
 Throughput in MB/s, **higher is better**:
 
-| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | 2.2.2 / OpenSSL |
+| | crypton 1.1.5 | crypton 2.2.4 | OpenSSL | 2.2.4 / OpenSSL |
 | --- | ---: | ---: | ---: | ---: |
-| AES-128-GCM | 1336 | **6037** | 4050 | 1.49 |
-| AES-256-GCM | 1093 | **5490** | 3769 | 1.46 |
-| ChaCha20-Poly1305 | 399 | 2196 | 2222 | 0.99 |
-| SHA-1 | 729 | 1663 | 1682 | 0.99 |
-| SHA-256 | 289 | 1586 | 1579 | 1.00 |
-| SHA-512 | 448 | 770 | 750 | 1.03 |
-| SHA3-256 | 109 | 421 | 425 | 0.99 |
+| AES-128-GCM | 1335 | **6041** | 4066 | 1.49 |
+| AES-256-GCM | 1093 | **5492** | 3766 | 1.46 |
+| ChaCha20-Poly1305 | 399 | 2195 | 2222 | 0.99 |
+| SHA-1 | 727 | 1663 | 1672 | 0.99 |
+| SHA-256 | 289 | 1585 | 1576 | 1.01 |
+| SHA-512 | 448 | 770 | 749 | 1.03 |
+| SHA3-256 | 109 | 421 | 429 | 0.98 |
 
 Time per operation in microseconds, **lower is better**:
 
-| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | OpenSSL / 2.2.2 |
+| | crypton 1.1.5 | crypton 2.2.4 | OpenSSL | OpenSSL / 2.2.4 |
 | --- | ---: | ---: | ---: | ---: |
-| X25519 | 44.06 | 28.54 | 36.50 | 1.28 |
-| ECDH P-256 | 164.5 | 50.56 | 51.62 | 1.02 |
-| ECDH P-384 | 2241 | **164.3** | 833.3 | 5.07 |
-| Ed25519 sign | 29.78 | 18.61 | 33.51 | 1.80 |
-| Ed25519 verify | 48.32 | 48.14 | 110.1 | 2.29 |
-| ECDSA P-256 sign | 81.62 | 18.71 | 21.96 | 1.17 |
-| ECDSA P-256 verify | 232.0 | 70.32 | 67.53 | 0.96 |
-| ECDSA P-384 sign | 2270 | **304.1** | 880.3 | 2.89 |
-| ECDSA P-384 verify | 2678 | **472.0** | 722.1 | 1.53 |
-| RSA-2048 sign/decrypt | 759.7 | 614.3 | 659.2 | 1.07 |
-| RSA-2048 verify/encrypt | 33.19 | 28.09 | 18.85 | 0.67 |
-| RSA-3072 sign/decrypt | 2500 | 2316 | 2008 | 0.87 |
-| RSA-3072 verify/encrypt | 65.97 | 63.47 | 40.12 | 0.63 |
+| X25519 | 44.38 | 28.29 | 36.61 | 1.29 |
+| ECDH P-256 | 164.0 | 51.31 | 51.70 | 1.01 |
+| ECDH P-384 | 2242 | **164.3** | 836.1 | 5.09 |
+| Ed25519 sign | 43.86 | 18.50 | 33.74 | 1.82 |
+| Ed25519 verify | 48.30 | 48.43 | 109.8 | 2.27 |
+| ECDSA P-256 sign | 81.80 | 19.72 | 21.84 | 1.11 |
+| ECDSA P-256 verify | 231.8 | 70.47 | 67.55 | 0.96 |
+| ECDSA P-384 sign | 2267 | **305.2** | 879.5 | 2.88 |
+| ECDSA P-384 verify | 2698 | **473.6** | 725.2 | 1.53 |
+| RSA-2048 sign/decrypt | 760.1 | 612.3 | 659.6 | 1.08 |
+| RSA-2048 verify/encrypt | 33.61 | 23.50 | 18.88 | 0.80 |
+| RSA-3072 sign/decrypt | 2499 | 2324 | 2012 | 0.87 |
+| RSA-3072 verify/encrypt | 66.80 | 61.91 | 40.14 | 0.65 |
 
 ### AArch64
 
@@ -146,37 +150,37 @@
 
 Throughput in MB/s, **higher is better**:
 
-| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | 2.2.2 / OpenSSL |
+| | crypton 1.1.5 | crypton 2.2.4 | OpenSSL | 2.2.4 / OpenSSL |
 | --- | ---: | ---: | ---: | ---: |
-| AES-128-GCM | 127 | **11661** | 10764 | 1.08 |
-| AES-256-GCM | 98 | **9764** | 9187 | 1.06 |
-| ChaCha20-Poly1305 | 767 | 2249 | 2263 | 0.99 |
-| SHA-1 | 1215 | 3383 | 3357 | 1.01 |
-| SHA-256 | 478 | 3391 | 3353 | 1.01 |
-| SHA-512 | 733 | 1847 | 1835 | 1.01 |
-| SHA3-256 | 549 | 1084 | 1073 | 1.01 |
+| AES-128-GCM | 131 | **12052** | 10922 | 1.10 |
+| AES-256-GCM | 99 | **10192** | 9208 | 1.11 |
+| ChaCha20-Poly1305 | 783 | 2342 | 2261 | 1.04 |
+| SHA-1 | 1234 | 3383 | 3347 | 1.01 |
+| SHA-256 | 486 | 3392 | 3354 | 1.01 |
+| SHA-512 | 742 | 1869 | 1860 | 1.00 |
+| SHA3-256 | 552 | 1096 | 1092 | 1.00 |
 
 Time per operation in microseconds, **lower is better**:
 
-| | crypton 1.1.5 | crypton 2.2.2 | OpenSSL | OpenSSL / 2.2.2 |
+| | crypton 1.1.5 | crypton 2.2.4 | OpenSSL | OpenSSL / 2.2.4 |
 | --- | ---: | ---: | ---: | ---: |
-| X25519 | 18.27 | **11.55** | 15.38 | 1.33 |
-| ECDH P-256 | 68.80 | **20.15** | 24.45 | 1.21 |
-| ECDH P-384 | 3277 | **72.17** | 374.3 | 5.19 |
-| Ed25519 sign | 13.42 | **7.450** | 13.27 | 1.78 |
-| Ed25519 verify | 18.30 | 18.30 | 34.44 | 1.88 |
-| ECDSA P-256 sign | 32.13 | **6.417** | 10.68 | 1.66 |
-| ECDSA P-256 verify | 95.07 | **26.68** | 32.27 | 1.21 |
-| ECDSA P-384 sign | 3241 | **124.7** | 392.8 | 3.15 |
-| ECDSA P-384 verify | 3885 | **203.8** | 329.3 | 1.62 |
-| RSA-2048 sign/decrypt | 451.0 | 458.7 | 320.3 | 0.70 |
-| RSA-2048 verify/encrypt | 18.12 | 15.58 | 8.400 | 0.54 |
-| RSA-3072 sign/decrypt | 1474 | 1317 | 927.7 | 0.70 |
-| RSA-3072 verify/encrypt | 47.85 | 44.20 | 17.84 | 0.40 |
+| X25519 | 17.92 | **12.02** | 15.32 | 1.28 |
+| ECDH P-256 | 67.50 | **19.05** | 24.36 | 1.28 |
+| ECDH P-384 | 3256 | **71.78** | 373.1 | 5.20 |
+| Ed25519 sign | 13.38 | **7.717** | 13.31 | 1.72 |
+| Ed25519 verify | 18.32 | 18.18 | 34.77 | 1.91 |
+| ECDSA P-256 sign | 31.08 | **6.500** | 10.66 | 1.64 |
+| ECDSA P-256 verify | 94.27 | **26.58** | 32.25 | 1.21 |
+| ECDSA P-384 sign | 3225 | **124.0** | 394.2 | 3.18 |
+| ECDSA P-384 verify | 3866 | **203.4** | 332.3 | 1.63 |
+| RSA-2048 sign/decrypt | 451.3 | 318.4 | 321.5 | 1.01 |
+| RSA-2048 verify/encrypt | 18.15 | 11.12 | 8.405 | 0.76 |
+| RSA-3072 sign/decrypt | 1473 | 937.4 | 931.1 | 0.99 |
+| RSA-3072 verify/encrypt | 47.95 | 43.63 | 17.89 | 0.41 |
 
 ### What the numbers say
 
-There are two changes behind the 1.1.5 column and the 2.2.2 one, not a
+There are two changes behind the 1.1.5 column and the 2.2.4 one, not a
 single steady improvement.
 
 The first, in 2.0.0, was a rewrite: the bulk algorithms moved into C, the
@@ -204,25 +208,34 @@
 it is Apache-2.0 only, and Intel and CloudFlare hold copyright in it besides
 OpenSSL, so nobody is in a position to relicense it.
 
-Where crypton is behind, which is now the RSA rows on both architectures and
-ECDSA P-256 verification on x86-64, there is one reason.  The AES-GCM rows
+crypton is behind in a few rows now: RSA verification on both architectures,
+and RSA-3072 signing and ECDSA P-256 verification on x86-64.  The AES-GCM rows
 were the other half of this section until 2.1.5; they are ahead on both
 machines now, and what the instructions do is still worth setting out.
 
 *RSA.*  2.0.0 made signing slower than 1.1.5 on purpose: its modular
 exponentiation stopped indexing a table with the bits of the exponent, and
-hiding the exponent is what the difference bought.  On x86-64 that cost is
-more than repaid -- s2n-bignum's Montgomery multiplication is twice the C's,
-because the C cannot form the two carry chains `ADCX` and `ADOX` give, and
-2.2.2 signs in less than 1.1.5 took, at 3072 bits as well as 2048, while
-keeping what 2.0.0 gained.  On AArch64 there is nothing to use: s2n-bignum's
-routines there, the five that help on x86-64 and the generic ones alike,
-measure no better than the C, so the C stays and the gap with it.  No
-portable C closes that gap either -- the measurements are in
-[#275](https://github.com/kazu-yamamoto/crypton/issues/275).  Verification
-does not move much either way: its exponent is 65537, seventeen bits, and
-there is no exponentiation to speak of.
+hiding the exponent is what the difference bought.  2.2.4 has repaid that
+cost on both machines, by different means.  On x86-64 s2n-bignum's
+Montgomery multiplication is twice the C's, because the C cannot form the two
+carry chains `ADCX` and `ADOX` give, and 2.2.4 signs in less than 1.1.5
+took, at 3072 bits as well as 2048.  On AArch64 s2n-bignum's routines measure
+no better than the C, so the gain there is the C's own: the multiplication
+and squaring for each key size are generated and unrolled, with the
+reduction folded into each column as in Koç, Acar and Kaliski's FIPS method,
+and signing is level with OpenSSL.  The measurements are in
+[#275](https://github.com/kazu-yamamoto/crypton/issues/275).
 
+On processors with AVX-512 IFMA, Intel Xeons from Ice Lake and AMD from Zen 4,
+2.2.4 computes the two halves of the CRT together in 52-bit digits, Gueron and
+Krasnov's method and the one OpenSSL takes there.  Neither machine above has
+IFMA, so neither table shows it.
+
+Verification's exponent is 65537, seventeen bits, so there is little
+exponentiation to speed up and the work around it counts.  2.2.4 keeps R^2,
+the Montgomery constant of a modulus, for the moduli it has seen, which is
+most of what the RSA-2048 verification rows gained.
+
 *The wide AES instructions.*  `VAES` and `VPCLMULQDQ` do two blocks where
 `AES-NI` and `PCLMULQDQ` do one, and four in their 512-bit form.  crypton uses
 the 256-bit form where the processor has it, which is Zen 3 and Ice Lake
@@ -240,7 +253,7 @@
 takes a block at a time where crypton takes two.  The same idea as theirs,
 one step further down the feature ladder; not a better one.
 
-The 512-bit path arrived after 2.1.2, so it is in the 2.2.2 column -- but
+The 512-bit path arrived after 2.1.2, so it is in the 2.2.4 column -- but
 neither machine in the tables above has AVX-512, so neither column shows it.
 On the runners that do, measured over 16 KiB in MB/s: an EPYC 9V45 (Zen 5)
 goes from 9616 to 14268 with it, a Xeon 6973P-C from 8095 to 9848, a Xeon
@@ -265,7 +278,7 @@
 key from the secret key every time it signs, so that a caller who passes a
 public key that does not match cannot be made to leak the private one.  That
 costs a second scalar multiplication, which OpenSSL's signing does not pay --
-and the row is still 1.78 on AArch64 and 1.80 on x86-64, so the safety is had
+and the row is still 1.72 on AArch64 and 1.82 on x86-64, so the safety is had
 for nothing here rather than paid for.
 
 Ed25519 verification wanted one too, for an unhappier reason, and 2.2.1
diff --git a/cbits/crypton_mont.h b/cbits/crypton_mont.h
--- a/cbits/crypton_mont.h
+++ b/cbits/crypton_mont.h
@@ -1,9015 +1,13445 @@
 /* Generated by cbits/crypton_mont.py; do not edit.
  *
  * Montgomery multiplication and squaring for AArch64 at 16, 24 and 32 limbs,
- * the halves of RSA-2048, -3072 and -4096.  Each answers what mont_mul and
- * mont_sqr answer. */
-#ifndef CRYPTON_MONT_H
-#define CRYPTON_MONT_H
-
-#include "crypton_bignum.h"
-
-/* (t2:t1:t0) += x * y */
-#define MONT_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_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) += (s2:s1:s0) */
-#define MONT_ADD(t0, t1, t2, s0, s1, s2)                                \
-	__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")
-
-/* (s2:s1:s0) *= 2 */
-#define MONT_DBL(s0, s1, s2)                                            \
-	do {                                                                \
-		s2 = (s2 << 1) | (s1 >> 63);                                    \
-		s1 = (s1 << 1) | (s0 >> 63);                                    \
-		s0 <<= 1;                                                       \
-	} while (0)
-
-/* r = a * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
-static void crypton_mont_mul16(limb_t *r, const limb_t *a, const limb_t *b,
-                               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, v0, v1, v2, w0, w1, w2, borrow, take;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], b[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MAC(t0, t1, t2, a[0], b[1]);
-	MONT_MUL(v0, v1, v2, a[1], b[0]);
-	MONT_MUL(w0, w1, w2, u[0], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MAC(t0, t1, t2, a[0], b[2]);
-	MONT_MUL(v0, v1, v2, a[1], b[1]);
-	MONT_MUL(w0, w1, w2, a[2], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[2]);
-	MONT_MAC(v0, v1, v2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MAC(t0, t1, t2, a[0], b[3]);
-	MONT_MUL(v0, v1, v2, a[1], b[2]);
-	MONT_MUL(w0, w1, w2, a[2], b[1]);
-	MONT_MAC(t0, t1, t2, a[3], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[3]);
-	MONT_MAC(w0, w1, w2, u[1], m[2]);
-	MONT_MAC(t0, t1, t2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MAC(t0, t1, t2, a[0], b[4]);
-	MONT_MUL(v0, v1, v2, a[1], b[3]);
-	MONT_MUL(w0, w1, w2, a[2], b[2]);
-	MONT_MAC(t0, t1, t2, a[3], b[1]);
-	MONT_MAC(v0, v1, v2, a[4], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[4]);
-	MONT_MAC(t0, t1, t2, u[1], m[3]);
-	MONT_MAC(v0, v1, v2, u[2], m[2]);
-	MONT_MAC(w0, w1, w2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MAC(t0, t1, t2, a[0], b[5]);
-	MONT_MUL(v0, v1, v2, a[1], b[4]);
-	MONT_MUL(w0, w1, w2, a[2], b[3]);
-	MONT_MAC(t0, t1, t2, a[3], b[2]);
-	MONT_MAC(v0, v1, v2, a[4], b[1]);
-	MONT_MAC(w0, w1, w2, a[5], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MAC(v0, v1, v2, u[1], m[4]);
-	MONT_MAC(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MAC(t0, t1, t2, a[0], b[6]);
-	MONT_MUL(v0, v1, v2, a[1], b[5]);
-	MONT_MUL(w0, w1, w2, a[2], b[4]);
-	MONT_MAC(t0, t1, t2, a[3], b[3]);
-	MONT_MAC(v0, v1, v2, a[4], b[2]);
-	MONT_MAC(w0, w1, w2, a[5], b[1]);
-	MONT_MAC(t0, t1, t2, a[6], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[6]);
-	MONT_MAC(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MAC(t0, t1, t2, a[0], b[7]);
-	MONT_MUL(v0, v1, v2, a[1], b[6]);
-	MONT_MUL(w0, w1, w2, a[2], b[5]);
-	MONT_MAC(t0, t1, t2, a[3], b[4]);
-	MONT_MAC(v0, v1, v2, a[4], b[3]);
-	MONT_MAC(w0, w1, w2, a[5], b[2]);
-	MONT_MAC(t0, t1, t2, a[6], b[1]);
-	MONT_MAC(v0, v1, v2, a[7], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[7]);
-	MONT_MAC(t0, t1, t2, u[1], m[6]);
-	MONT_MAC(v0, v1, v2, u[2], m[5]);
-	MONT_MAC(w0, w1, w2, u[3], m[4]);
-	MONT_MAC(t0, t1, t2, u[4], m[3]);
-	MONT_MAC(v0, v1, v2, u[5], m[2]);
-	MONT_MAC(w0, w1, w2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MAC(t0, t1, t2, a[0], b[8]);
-	MONT_MUL(v0, v1, v2, a[1], b[7]);
-	MONT_MUL(w0, w1, w2, a[2], b[6]);
-	MONT_MAC(t0, t1, t2, a[3], b[5]);
-	MONT_MAC(v0, v1, v2, a[4], b[4]);
-	MONT_MAC(w0, w1, w2, a[5], b[3]);
-	MONT_MAC(t0, t1, t2, a[6], b[2]);
-	MONT_MAC(v0, v1, v2, a[7], b[1]);
-	MONT_MAC(w0, w1, w2, a[8], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[8]);
-	MONT_MAC(v0, v1, v2, u[1], m[7]);
-	MONT_MAC(w0, w1, w2, u[2], m[6]);
-	MONT_MAC(t0, t1, t2, u[3], m[5]);
-	MONT_MAC(v0, v1, v2, u[4], m[4]);
-	MONT_MAC(w0, w1, w2, u[5], m[3]);
-	MONT_MAC(t0, t1, t2, u[6], m[2]);
-	MONT_MAC(v0, v1, v2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MAC(t0, t1, t2, a[0], b[9]);
-	MONT_MUL(v0, v1, v2, a[1], b[8]);
-	MONT_MUL(w0, w1, w2, a[2], b[7]);
-	MONT_MAC(t0, t1, t2, a[3], b[6]);
-	MONT_MAC(v0, v1, v2, a[4], b[5]);
-	MONT_MAC(w0, w1, w2, a[5], b[4]);
-	MONT_MAC(t0, t1, t2, a[6], b[3]);
-	MONT_MAC(v0, v1, v2, a[7], b[2]);
-	MONT_MAC(w0, w1, w2, a[8], b[1]);
-	MONT_MAC(t0, t1, t2, a[9], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[9]);
-	MONT_MAC(w0, w1, w2, u[1], m[8]);
-	MONT_MAC(t0, t1, t2, u[2], m[7]);
-	MONT_MAC(v0, v1, v2, u[3], m[6]);
-	MONT_MAC(w0, w1, w2, u[4], m[5]);
-	MONT_MAC(t0, t1, t2, u[5], m[4]);
-	MONT_MAC(v0, v1, v2, u[6], m[3]);
-	MONT_MAC(w0, w1, w2, u[7], m[2]);
-	MONT_MAC(t0, t1, t2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MAC(t0, t1, t2, a[0], b[10]);
-	MONT_MUL(v0, v1, v2, a[1], b[9]);
-	MONT_MUL(w0, w1, w2, a[2], b[8]);
-	MONT_MAC(t0, t1, t2, a[3], b[7]);
-	MONT_MAC(v0, v1, v2, a[4], b[6]);
-	MONT_MAC(w0, w1, w2, a[5], b[5]);
-	MONT_MAC(t0, t1, t2, a[6], b[4]);
-	MONT_MAC(v0, v1, v2, a[7], b[3]);
-	MONT_MAC(w0, w1, w2, a[8], b[2]);
-	MONT_MAC(t0, t1, t2, a[9], b[1]);
-	MONT_MAC(v0, v1, v2, a[10], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[10]);
-	MONT_MAC(t0, t1, t2, u[1], m[9]);
-	MONT_MAC(v0, v1, v2, u[2], m[8]);
-	MONT_MAC(w0, w1, w2, u[3], m[7]);
-	MONT_MAC(t0, t1, t2, u[4], m[6]);
-	MONT_MAC(v0, v1, v2, u[5], m[5]);
-	MONT_MAC(w0, w1, w2, u[6], m[4]);
-	MONT_MAC(t0, t1, t2, u[7], m[3]);
-	MONT_MAC(v0, v1, v2, u[8], m[2]);
-	MONT_MAC(w0, w1, w2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MAC(t0, t1, t2, a[0], b[11]);
-	MONT_MUL(v0, v1, v2, a[1], b[10]);
-	MONT_MUL(w0, w1, w2, a[2], b[9]);
-	MONT_MAC(t0, t1, t2, a[3], b[8]);
-	MONT_MAC(v0, v1, v2, a[4], b[7]);
-	MONT_MAC(w0, w1, w2, a[5], b[6]);
-	MONT_MAC(t0, t1, t2, a[6], b[5]);
-	MONT_MAC(v0, v1, v2, a[7], b[4]);
-	MONT_MAC(w0, w1, w2, a[8], b[3]);
-	MONT_MAC(t0, t1, t2, a[9], b[2]);
-	MONT_MAC(v0, v1, v2, a[10], b[1]);
-	MONT_MAC(w0, w1, w2, a[11], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MAC(v0, v1, v2, u[1], m[10]);
-	MONT_MAC(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MAC(t0, t1, t2, a[0], b[12]);
-	MONT_MUL(v0, v1, v2, a[1], b[11]);
-	MONT_MUL(w0, w1, w2, a[2], b[10]);
-	MONT_MAC(t0, t1, t2, a[3], b[9]);
-	MONT_MAC(v0, v1, v2, a[4], b[8]);
-	MONT_MAC(w0, w1, w2, a[5], b[7]);
-	MONT_MAC(t0, t1, t2, a[6], b[6]);
-	MONT_MAC(v0, v1, v2, a[7], b[5]);
-	MONT_MAC(w0, w1, w2, a[8], b[4]);
-	MONT_MAC(t0, t1, t2, a[9], b[3]);
-	MONT_MAC(v0, v1, v2, a[10], b[2]);
-	MONT_MAC(w0, w1, w2, a[11], b[1]);
-	MONT_MAC(t0, t1, t2, a[12], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[12]);
-	MONT_MAC(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MAC(t0, t1, t2, a[0], b[13]);
-	MONT_MUL(v0, v1, v2, a[1], b[12]);
-	MONT_MUL(w0, w1, w2, a[2], b[11]);
-	MONT_MAC(t0, t1, t2, a[3], b[10]);
-	MONT_MAC(v0, v1, v2, a[4], b[9]);
-	MONT_MAC(w0, w1, w2, a[5], b[8]);
-	MONT_MAC(t0, t1, t2, a[6], b[7]);
-	MONT_MAC(v0, v1, v2, a[7], b[6]);
-	MONT_MAC(w0, w1, w2, a[8], b[5]);
-	MONT_MAC(t0, t1, t2, a[9], b[4]);
-	MONT_MAC(v0, v1, v2, a[10], b[3]);
-	MONT_MAC(w0, w1, w2, a[11], b[2]);
-	MONT_MAC(t0, t1, t2, a[12], b[1]);
-	MONT_MAC(v0, v1, v2, a[13], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[13]);
-	MONT_MAC(t0, t1, t2, u[1], m[12]);
-	MONT_MAC(v0, v1, v2, u[2], m[11]);
-	MONT_MAC(w0, w1, w2, u[3], m[10]);
-	MONT_MAC(t0, t1, t2, u[4], m[9]);
-	MONT_MAC(v0, v1, v2, u[5], m[8]);
-	MONT_MAC(w0, w1, w2, u[6], m[7]);
-	MONT_MAC(t0, t1, t2, u[7], m[6]);
-	MONT_MAC(v0, v1, v2, u[8], m[5]);
-	MONT_MAC(w0, w1, w2, u[9], m[4]);
-	MONT_MAC(t0, t1, t2, u[10], m[3]);
-	MONT_MAC(v0, v1, v2, u[11], m[2]);
-	MONT_MAC(w0, w1, w2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MAC(t0, t1, t2, a[0], b[14]);
-	MONT_MUL(v0, v1, v2, a[1], b[13]);
-	MONT_MUL(w0, w1, w2, a[2], b[12]);
-	MONT_MAC(t0, t1, t2, a[3], b[11]);
-	MONT_MAC(v0, v1, v2, a[4], b[10]);
-	MONT_MAC(w0, w1, w2, a[5], b[9]);
-	MONT_MAC(t0, t1, t2, a[6], b[8]);
-	MONT_MAC(v0, v1, v2, a[7], b[7]);
-	MONT_MAC(w0, w1, w2, a[8], b[6]);
-	MONT_MAC(t0, t1, t2, a[9], b[5]);
-	MONT_MAC(v0, v1, v2, a[10], b[4]);
-	MONT_MAC(w0, w1, w2, a[11], b[3]);
-	MONT_MAC(t0, t1, t2, a[12], b[2]);
-	MONT_MAC(v0, v1, v2, a[13], b[1]);
-	MONT_MAC(w0, w1, w2, a[14], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[14]);
-	MONT_MAC(v0, v1, v2, u[1], m[13]);
-	MONT_MAC(w0, w1, w2, u[2], m[12]);
-	MONT_MAC(t0, t1, t2, u[3], m[11]);
-	MONT_MAC(v0, v1, v2, u[4], m[10]);
-	MONT_MAC(w0, w1, w2, u[5], m[9]);
-	MONT_MAC(t0, t1, t2, u[6], m[8]);
-	MONT_MAC(v0, v1, v2, u[7], m[7]);
-	MONT_MAC(w0, w1, w2, u[8], m[6]);
-	MONT_MAC(t0, t1, t2, u[9], m[5]);
-	MONT_MAC(v0, v1, v2, u[10], m[4]);
-	MONT_MAC(w0, w1, w2, u[11], m[3]);
-	MONT_MAC(t0, t1, t2, u[12], m[2]);
-	MONT_MAC(v0, v1, v2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MAC(t0, t1, t2, a[0], b[15]);
-	MONT_MUL(v0, v1, v2, a[1], b[14]);
-	MONT_MUL(w0, w1, w2, a[2], b[13]);
-	MONT_MAC(t0, t1, t2, a[3], b[12]);
-	MONT_MAC(v0, v1, v2, a[4], b[11]);
-	MONT_MAC(w0, w1, w2, a[5], b[10]);
-	MONT_MAC(t0, t1, t2, a[6], b[9]);
-	MONT_MAC(v0, v1, v2, a[7], b[8]);
-	MONT_MAC(w0, w1, w2, a[8], b[7]);
-	MONT_MAC(t0, t1, t2, a[9], b[6]);
-	MONT_MAC(v0, v1, v2, a[10], b[5]);
-	MONT_MAC(w0, w1, w2, a[11], b[4]);
-	MONT_MAC(t0, t1, t2, a[12], b[3]);
-	MONT_MAC(v0, v1, v2, a[13], b[2]);
-	MONT_MAC(w0, w1, w2, a[14], b[1]);
-	MONT_MAC(t0, t1, t2, a[15], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[15]);
-	MONT_MAC(w0, w1, w2, u[1], m[14]);
-	MONT_MAC(t0, t1, t2, u[2], m[13]);
-	MONT_MAC(v0, v1, v2, u[3], m[12]);
-	MONT_MAC(w0, w1, w2, u[4], m[11]);
-	MONT_MAC(t0, t1, t2, u[5], m[10]);
-	MONT_MAC(v0, v1, v2, u[6], m[9]);
-	MONT_MAC(w0, w1, w2, u[7], m[8]);
-	MONT_MAC(t0, t1, t2, u[8], m[7]);
-	MONT_MAC(v0, v1, v2, u[9], m[6]);
-	MONT_MAC(w0, w1, w2, u[10], m[5]);
-	MONT_MAC(t0, t1, t2, u[11], m[4]);
-	MONT_MAC(v0, v1, v2, u[12], m[3]);
-	MONT_MAC(w0, w1, w2, u[13], m[2]);
-	MONT_MAC(t0, t1, t2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MAC(t0, t1, t2, a[1], b[15]);
-	MONT_MUL(v0, v1, v2, a[2], b[14]);
-	MONT_MUL(w0, w1, w2, a[3], b[13]);
-	MONT_MAC(t0, t1, t2, a[4], b[12]);
-	MONT_MAC(v0, v1, v2, a[5], b[11]);
-	MONT_MAC(w0, w1, w2, a[6], b[10]);
-	MONT_MAC(t0, t1, t2, a[7], b[9]);
-	MONT_MAC(v0, v1, v2, a[8], b[8]);
-	MONT_MAC(w0, w1, w2, a[9], b[7]);
-	MONT_MAC(t0, t1, t2, a[10], b[6]);
-	MONT_MAC(v0, v1, v2, a[11], b[5]);
-	MONT_MAC(w0, w1, w2, a[12], b[4]);
-	MONT_MAC(t0, t1, t2, a[13], b[3]);
-	MONT_MAC(v0, v1, v2, a[14], b[2]);
-	MONT_MAC(w0, w1, w2, a[15], b[1]);
-	MONT_MAC(t0, t1, t2, u[1], m[15]);
-	MONT_MAC(v0, v1, v2, u[2], m[14]);
-	MONT_MAC(w0, w1, w2, u[3], m[13]);
-	MONT_MAC(t0, t1, t2, u[4], m[12]);
-	MONT_MAC(v0, v1, v2, u[5], m[11]);
-	MONT_MAC(w0, w1, w2, u[6], m[10]);
-	MONT_MAC(t0, t1, t2, u[7], m[9]);
-	MONT_MAC(v0, v1, v2, u[8], m[8]);
-	MONT_MAC(w0, w1, w2, u[9], m[7]);
-	MONT_MAC(t0, t1, t2, u[10], m[6]);
-	MONT_MAC(v0, v1, v2, u[11], m[5]);
-	MONT_MAC(w0, w1, w2, u[12], m[4]);
-	MONT_MAC(t0, t1, t2, u[13], m[3]);
-	MONT_MAC(v0, v1, v2, u[14], m[2]);
-	MONT_MAC(w0, w1, w2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MAC(t0, t1, t2, a[2], b[15]);
-	MONT_MUL(v0, v1, v2, a[3], b[14]);
-	MONT_MUL(w0, w1, w2, a[4], b[13]);
-	MONT_MAC(t0, t1, t2, a[5], b[12]);
-	MONT_MAC(v0, v1, v2, a[6], b[11]);
-	MONT_MAC(w0, w1, w2, a[7], b[10]);
-	MONT_MAC(t0, t1, t2, a[8], b[9]);
-	MONT_MAC(v0, v1, v2, a[9], b[8]);
-	MONT_MAC(w0, w1, w2, a[10], b[7]);
-	MONT_MAC(t0, t1, t2, a[11], b[6]);
-	MONT_MAC(v0, v1, v2, a[12], b[5]);
-	MONT_MAC(w0, w1, w2, a[13], b[4]);
-	MONT_MAC(t0, t1, t2, a[14], b[3]);
-	MONT_MAC(v0, v1, v2, a[15], b[2]);
-	MONT_MAC(w0, w1, w2, u[2], m[15]);
-	MONT_MAC(t0, t1, t2, u[3], m[14]);
-	MONT_MAC(v0, v1, v2, u[4], m[13]);
-	MONT_MAC(w0, w1, w2, u[5], m[12]);
-	MONT_MAC(t0, t1, t2, u[6], m[11]);
-	MONT_MAC(v0, v1, v2, u[7], m[10]);
-	MONT_MAC(w0, w1, w2, u[8], m[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[8]);
-	MONT_MAC(v0, v1, v2, u[10], m[7]);
-	MONT_MAC(w0, w1, w2, u[11], m[6]);
-	MONT_MAC(t0, t1, t2, u[12], m[5]);
-	MONT_MAC(v0, v1, v2, u[13], m[4]);
-	MONT_MAC(w0, w1, w2, u[14], m[3]);
-	MONT_MAC(t0, t1, t2, u[15], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MAC(t0, t1, t2, a[3], b[15]);
-	MONT_MUL(v0, v1, v2, a[4], b[14]);
-	MONT_MUL(w0, w1, w2, a[5], b[13]);
-	MONT_MAC(t0, t1, t2, a[6], b[12]);
-	MONT_MAC(v0, v1, v2, a[7], b[11]);
-	MONT_MAC(w0, w1, w2, a[8], b[10]);
-	MONT_MAC(t0, t1, t2, a[9], b[9]);
-	MONT_MAC(v0, v1, v2, a[10], b[8]);
-	MONT_MAC(w0, w1, w2, a[11], b[7]);
-	MONT_MAC(t0, t1, t2, a[12], b[6]);
-	MONT_MAC(v0, v1, v2, a[13], b[5]);
-	MONT_MAC(w0, w1, w2, a[14], b[4]);
-	MONT_MAC(t0, t1, t2, a[15], b[3]);
-	MONT_MAC(v0, v1, v2, u[3], m[15]);
-	MONT_MAC(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MAC(t0, t1, t2, a[4], b[15]);
-	MONT_MUL(v0, v1, v2, a[5], b[14]);
-	MONT_MUL(w0, w1, w2, a[6], b[13]);
-	MONT_MAC(t0, t1, t2, a[7], b[12]);
-	MONT_MAC(v0, v1, v2, a[8], b[11]);
-	MONT_MAC(w0, w1, w2, a[9], b[10]);
-	MONT_MAC(t0, t1, t2, a[10], b[9]);
-	MONT_MAC(v0, v1, v2, a[11], b[8]);
-	MONT_MAC(w0, w1, w2, a[12], b[7]);
-	MONT_MAC(t0, t1, t2, a[13], b[6]);
-	MONT_MAC(v0, v1, v2, a[14], b[5]);
-	MONT_MAC(w0, w1, w2, a[15], b[4]);
-	MONT_MAC(t0, t1, t2, u[4], m[15]);
-	MONT_MAC(v0, v1, v2, u[5], m[14]);
-	MONT_MAC(w0, w1, w2, u[6], m[13]);
-	MONT_MAC(t0, t1, t2, u[7], m[12]);
-	MONT_MAC(v0, v1, v2, u[8], m[11]);
-	MONT_MAC(w0, w1, w2, u[9], m[10]);
-	MONT_MAC(t0, t1, t2, u[10], m[9]);
-	MONT_MAC(v0, v1, v2, u[11], m[8]);
-	MONT_MAC(w0, w1, w2, u[12], m[7]);
-	MONT_MAC(t0, t1, t2, u[13], m[6]);
-	MONT_MAC(v0, v1, v2, u[14], m[5]);
-	MONT_MAC(w0, w1, w2, u[15], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MAC(t0, t1, t2, a[5], b[15]);
-	MONT_MUL(v0, v1, v2, a[6], b[14]);
-	MONT_MUL(w0, w1, w2, a[7], b[13]);
-	MONT_MAC(t0, t1, t2, a[8], b[12]);
-	MONT_MAC(v0, v1, v2, a[9], b[11]);
-	MONT_MAC(w0, w1, w2, a[10], b[10]);
-	MONT_MAC(t0, t1, t2, a[11], b[9]);
-	MONT_MAC(v0, v1, v2, a[12], b[8]);
-	MONT_MAC(w0, w1, w2, a[13], b[7]);
-	MONT_MAC(t0, t1, t2, a[14], b[6]);
-	MONT_MAC(v0, v1, v2, a[15], b[5]);
-	MONT_MAC(w0, w1, w2, u[5], m[15]);
-	MONT_MAC(t0, t1, t2, u[6], m[14]);
-	MONT_MAC(v0, v1, v2, u[7], m[13]);
-	MONT_MAC(w0, w1, w2, u[8], m[12]);
-	MONT_MAC(t0, t1, t2, u[9], m[11]);
-	MONT_MAC(v0, v1, v2, u[10], m[10]);
-	MONT_MAC(w0, w1, w2, u[11], m[9]);
-	MONT_MAC(t0, t1, t2, u[12], m[8]);
-	MONT_MAC(v0, v1, v2, u[13], m[7]);
-	MONT_MAC(w0, w1, w2, u[14], m[6]);
-	MONT_MAC(t0, t1, t2, u[15], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MAC(t0, t1, t2, a[6], b[15]);
-	MONT_MUL(v0, v1, v2, a[7], b[14]);
-	MONT_MUL(w0, w1, w2, a[8], b[13]);
-	MONT_MAC(t0, t1, t2, a[9], b[12]);
-	MONT_MAC(v0, v1, v2, a[10], b[11]);
-	MONT_MAC(w0, w1, w2, a[11], b[10]);
-	MONT_MAC(t0, t1, t2, a[12], b[9]);
-	MONT_MAC(v0, v1, v2, a[13], b[8]);
-	MONT_MAC(w0, w1, w2, a[14], b[7]);
-	MONT_MAC(t0, t1, t2, a[15], b[6]);
-	MONT_MAC(v0, v1, v2, u[6], m[15]);
-	MONT_MAC(w0, w1, w2, u[7], m[14]);
-	MONT_MAC(t0, t1, t2, u[8], m[13]);
-	MONT_MAC(v0, v1, v2, u[9], m[12]);
-	MONT_MAC(w0, w1, w2, u[10], m[11]);
-	MONT_MAC(t0, t1, t2, u[11], m[10]);
-	MONT_MAC(v0, v1, v2, u[12], m[9]);
-	MONT_MAC(w0, w1, w2, u[13], m[8]);
-	MONT_MAC(t0, t1, t2, u[14], m[7]);
-	MONT_MAC(v0, v1, v2, u[15], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MAC(t0, t1, t2, a[7], b[15]);
-	MONT_MUL(v0, v1, v2, a[8], b[14]);
-	MONT_MUL(w0, w1, w2, a[9], b[13]);
-	MONT_MAC(t0, t1, t2, a[10], b[12]);
-	MONT_MAC(v0, v1, v2, a[11], b[11]);
-	MONT_MAC(w0, w1, w2, a[12], b[10]);
-	MONT_MAC(t0, t1, t2, a[13], b[9]);
-	MONT_MAC(v0, v1, v2, a[14], b[8]);
-	MONT_MAC(w0, w1, w2, a[15], b[7]);
-	MONT_MAC(t0, t1, t2, u[7], m[15]);
-	MONT_MAC(v0, v1, v2, u[8], m[14]);
-	MONT_MAC(w0, w1, w2, u[9], m[13]);
-	MONT_MAC(t0, t1, t2, u[10], m[12]);
-	MONT_MAC(v0, v1, v2, u[11], m[11]);
-	MONT_MAC(w0, w1, w2, u[12], m[10]);
-	MONT_MAC(t0, t1, t2, u[13], m[9]);
-	MONT_MAC(v0, v1, v2, u[14], m[8]);
-	MONT_MAC(w0, w1, w2, u[15], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MAC(t0, t1, t2, a[8], b[15]);
-	MONT_MUL(v0, v1, v2, a[9], b[14]);
-	MONT_MUL(w0, w1, w2, a[10], b[13]);
-	MONT_MAC(t0, t1, t2, a[11], b[12]);
-	MONT_MAC(v0, v1, v2, a[12], b[11]);
-	MONT_MAC(w0, w1, w2, a[13], b[10]);
-	MONT_MAC(t0, t1, t2, a[14], b[9]);
-	MONT_MAC(v0, v1, v2, a[15], b[8]);
-	MONT_MAC(w0, w1, w2, u[8], m[15]);
-	MONT_MAC(t0, t1, t2, u[9], m[14]);
-	MONT_MAC(v0, v1, v2, u[10], m[13]);
-	MONT_MAC(w0, w1, w2, u[11], m[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[11]);
-	MONT_MAC(v0, v1, v2, u[13], m[10]);
-	MONT_MAC(w0, w1, w2, u[14], m[9]);
-	MONT_MAC(t0, t1, t2, u[15], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MAC(t0, t1, t2, a[9], b[15]);
-	MONT_MUL(v0, v1, v2, a[10], b[14]);
-	MONT_MUL(w0, w1, w2, a[11], b[13]);
-	MONT_MAC(t0, t1, t2, a[12], b[12]);
-	MONT_MAC(v0, v1, v2, a[13], b[11]);
-	MONT_MAC(w0, w1, w2, a[14], b[10]);
-	MONT_MAC(t0, t1, t2, a[15], b[9]);
-	MONT_MAC(v0, v1, v2, u[9], m[15]);
-	MONT_MAC(w0, w1, w2, u[10], m[14]);
-	MONT_MAC(t0, t1, t2, u[11], m[13]);
-	MONT_MAC(v0, v1, v2, u[12], m[12]);
-	MONT_MAC(w0, w1, w2, u[13], m[11]);
-	MONT_MAC(t0, t1, t2, u[14], m[10]);
-	MONT_MAC(v0, v1, v2, u[15], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MAC(t0, t1, t2, a[10], b[15]);
-	MONT_MUL(v0, v1, v2, a[11], b[14]);
-	MONT_MUL(w0, w1, w2, a[12], b[13]);
-	MONT_MAC(t0, t1, t2, a[13], b[12]);
-	MONT_MAC(v0, v1, v2, a[14], b[11]);
-	MONT_MAC(w0, w1, w2, a[15], b[10]);
-	MONT_MAC(t0, t1, t2, u[10], m[15]);
-	MONT_MAC(v0, v1, v2, u[11], m[14]);
-	MONT_MAC(w0, w1, w2, u[12], m[13]);
-	MONT_MAC(t0, t1, t2, u[13], m[12]);
-	MONT_MAC(v0, v1, v2, u[14], m[11]);
-	MONT_MAC(w0, w1, w2, u[15], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MAC(t0, t1, t2, a[11], b[15]);
-	MONT_MUL(v0, v1, v2, a[12], b[14]);
-	MONT_MUL(w0, w1, w2, a[13], b[13]);
-	MONT_MAC(t0, t1, t2, a[14], b[12]);
-	MONT_MAC(v0, v1, v2, a[15], b[11]);
-	MONT_MAC(w0, w1, w2, u[11], m[15]);
-	MONT_MAC(t0, t1, t2, u[12], m[14]);
-	MONT_MAC(v0, v1, v2, u[13], m[13]);
-	MONT_MAC(w0, w1, w2, u[14], m[12]);
-	MONT_MAC(t0, t1, t2, u[15], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MAC(t0, t1, t2, a[12], b[15]);
-	MONT_MUL(v0, v1, v2, a[13], b[14]);
-	MONT_MUL(w0, w1, w2, a[14], b[13]);
-	MONT_MAC(t0, t1, t2, a[15], b[12]);
-	MONT_MAC(v0, v1, v2, u[12], m[15]);
-	MONT_MAC(w0, w1, w2, u[13], m[14]);
-	MONT_MAC(t0, t1, t2, u[14], m[13]);
-	MONT_MAC(v0, v1, v2, u[15], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MAC(t0, t1, t2, a[13], b[15]);
-	MONT_MUL(v0, v1, v2, a[14], b[14]);
-	MONT_MUL(w0, w1, w2, a[15], b[13]);
-	MONT_MAC(t0, t1, t2, u[13], m[15]);
-	MONT_MAC(v0, v1, v2, u[14], m[14]);
-	MONT_MAC(w0, w1, w2, u[15], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MAC(t0, t1, t2, a[14], b[15]);
-	MONT_MUL(v0, v1, v2, a[15], b[14]);
-	MONT_MUL(w0, w1, w2, u[14], m[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MAC(t0, t1, t2, a[15], b[15]);
-	MONT_MUL(v0, v1, v2, u[15], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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_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, v0, v1, v2, w0, w1, w2, borrow, take;
-	limb_t s0, s1, s2, c0, c1, c2;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], a[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MUL(s0, s1, s2, a[0], a[1]);
-	MONT_MAC(t0, t1, t2, u[0], m[1]);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MUL(s0, s1, s2, a[0], a[2]);
-	MONT_MAC(t0, t1, t2, a[1], a[1]);
-	MONT_MUL(v0, v1, v2, u[0], m[2]);
-	MONT_MUL(w0, w1, w2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MUL(s0, s1, s2, a[0], a[3]);
-	MONT_MUL(c0, c1, c2, a[1], a[2]);
-	MONT_MAC(t0, t1, t2, u[0], m[3]);
-	MONT_MUL(v0, v1, v2, u[1], m[2]);
-	MONT_MUL(w0, w1, w2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MUL(s0, s1, s2, a[0], a[4]);
-	MONT_MUL(c0, c1, c2, a[1], a[3]);
-	MONT_MAC(t0, t1, t2, a[2], a[2]);
-	MONT_MUL(v0, v1, v2, u[0], m[4]);
-	MONT_MUL(w0, w1, w2, u[1], m[3]);
-	MONT_MAC(t0, t1, t2, u[2], m[2]);
-	MONT_MAC(v0, v1, v2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MUL(s0, s1, s2, a[0], a[5]);
-	MONT_MUL(c0, c1, c2, a[1], a[4]);
-	MONT_MAC(s0, s1, s2, a[2], a[3]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MUL(v0, v1, v2, u[1], m[4]);
-	MONT_MUL(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MUL(s0, s1, s2, a[0], a[6]);
-	MONT_MUL(c0, c1, c2, a[1], a[5]);
-	MONT_MAC(s0, s1, s2, a[2], a[4]);
-	MONT_MAC(t0, t1, t2, a[3], a[3]);
-	MONT_MUL(v0, v1, v2, u[0], m[6]);
-	MONT_MUL(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MUL(s0, s1, s2, a[0], a[7]);
-	MONT_MUL(c0, c1, c2, a[1], a[6]);
-	MONT_MAC(s0, s1, s2, a[2], a[5]);
-	MONT_MAC(c0, c1, c2, a[3], a[4]);
-	MONT_MAC(t0, t1, t2, u[0], m[7]);
-	MONT_MUL(v0, v1, v2, u[1], m[6]);
-	MONT_MUL(w0, w1, w2, u[2], m[5]);
-	MONT_MAC(t0, t1, t2, u[3], m[4]);
-	MONT_MAC(v0, v1, v2, u[4], m[3]);
-	MONT_MAC(w0, w1, w2, u[5], m[2]);
-	MONT_MAC(t0, t1, t2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MUL(s0, s1, s2, a[0], a[8]);
-	MONT_MUL(c0, c1, c2, a[1], a[7]);
-	MONT_MAC(s0, s1, s2, a[2], a[6]);
-	MONT_MAC(c0, c1, c2, a[3], a[5]);
-	MONT_MAC(t0, t1, t2, a[4], a[4]);
-	MONT_MUL(v0, v1, v2, u[0], m[8]);
-	MONT_MUL(w0, w1, w2, u[1], m[7]);
-	MONT_MAC(t0, t1, t2, u[2], m[6]);
-	MONT_MAC(v0, v1, v2, u[3], m[5]);
-	MONT_MAC(w0, w1, w2, u[4], m[4]);
-	MONT_MAC(t0, t1, t2, u[5], m[3]);
-	MONT_MAC(v0, v1, v2, u[6], m[2]);
-	MONT_MAC(w0, w1, w2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MUL(s0, s1, s2, a[0], a[9]);
-	MONT_MUL(c0, c1, c2, a[1], a[8]);
-	MONT_MAC(s0, s1, s2, a[2], a[7]);
-	MONT_MAC(c0, c1, c2, a[3], a[6]);
-	MONT_MAC(s0, s1, s2, a[4], a[5]);
-	MONT_MAC(t0, t1, t2, u[0], m[9]);
-	MONT_MUL(v0, v1, v2, u[1], m[8]);
-	MONT_MUL(w0, w1, w2, u[2], m[7]);
-	MONT_MAC(t0, t1, t2, u[3], m[6]);
-	MONT_MAC(v0, v1, v2, u[4], m[5]);
-	MONT_MAC(w0, w1, w2, u[5], m[4]);
-	MONT_MAC(t0, t1, t2, u[6], m[3]);
-	MONT_MAC(v0, v1, v2, u[7], m[2]);
-	MONT_MAC(w0, w1, w2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MUL(s0, s1, s2, a[0], a[10]);
-	MONT_MUL(c0, c1, c2, a[1], a[9]);
-	MONT_MAC(s0, s1, s2, a[2], a[8]);
-	MONT_MAC(c0, c1, c2, a[3], a[7]);
-	MONT_MAC(s0, s1, s2, a[4], a[6]);
-	MONT_MAC(t0, t1, t2, a[5], a[5]);
-	MONT_MUL(v0, v1, v2, u[0], m[10]);
-	MONT_MUL(w0, w1, w2, u[1], m[9]);
-	MONT_MAC(t0, t1, t2, u[2], m[8]);
-	MONT_MAC(v0, v1, v2, u[3], m[7]);
-	MONT_MAC(w0, w1, w2, u[4], m[6]);
-	MONT_MAC(t0, t1, t2, u[5], m[5]);
-	MONT_MAC(v0, v1, v2, u[6], m[4]);
-	MONT_MAC(w0, w1, w2, u[7], m[3]);
-	MONT_MAC(t0, t1, t2, u[8], m[2]);
-	MONT_MAC(v0, v1, v2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MUL(s0, s1, s2, a[0], a[11]);
-	MONT_MUL(c0, c1, c2, a[1], a[10]);
-	MONT_MAC(s0, s1, s2, a[2], a[9]);
-	MONT_MAC(c0, c1, c2, a[3], a[8]);
-	MONT_MAC(s0, s1, s2, a[4], a[7]);
-	MONT_MAC(c0, c1, c2, a[5], a[6]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MUL(v0, v1, v2, u[1], m[10]);
-	MONT_MUL(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MUL(s0, s1, s2, a[0], a[12]);
-	MONT_MUL(c0, c1, c2, a[1], a[11]);
-	MONT_MAC(s0, s1, s2, a[2], a[10]);
-	MONT_MAC(c0, c1, c2, a[3], a[9]);
-	MONT_MAC(s0, s1, s2, a[4], a[8]);
-	MONT_MAC(c0, c1, c2, a[5], a[7]);
-	MONT_MAC(t0, t1, t2, a[6], a[6]);
-	MONT_MUL(v0, v1, v2, u[0], m[12]);
-	MONT_MUL(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MUL(s0, s1, s2, a[0], a[13]);
-	MONT_MUL(c0, c1, c2, a[1], a[12]);
-	MONT_MAC(s0, s1, s2, a[2], a[11]);
-	MONT_MAC(c0, c1, c2, a[3], a[10]);
-	MONT_MAC(s0, s1, s2, a[4], a[9]);
-	MONT_MAC(c0, c1, c2, a[5], a[8]);
-	MONT_MAC(s0, s1, s2, a[6], a[7]);
-	MONT_MAC(t0, t1, t2, u[0], m[13]);
-	MONT_MUL(v0, v1, v2, u[1], m[12]);
-	MONT_MUL(w0, w1, w2, u[2], m[11]);
-	MONT_MAC(t0, t1, t2, u[3], m[10]);
-	MONT_MAC(v0, v1, v2, u[4], m[9]);
-	MONT_MAC(w0, w1, w2, u[5], m[8]);
-	MONT_MAC(t0, t1, t2, u[6], m[7]);
-	MONT_MAC(v0, v1, v2, u[7], m[6]);
-	MONT_MAC(w0, w1, w2, u[8], m[5]);
-	MONT_MAC(t0, t1, t2, u[9], m[4]);
-	MONT_MAC(v0, v1, v2, u[10], m[3]);
-	MONT_MAC(w0, w1, w2, u[11], m[2]);
-	MONT_MAC(t0, t1, t2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MUL(s0, s1, s2, a[0], a[14]);
-	MONT_MUL(c0, c1, c2, a[1], a[13]);
-	MONT_MAC(s0, s1, s2, a[2], a[12]);
-	MONT_MAC(c0, c1, c2, a[3], a[11]);
-	MONT_MAC(s0, s1, s2, a[4], a[10]);
-	MONT_MAC(c0, c1, c2, a[5], a[9]);
-	MONT_MAC(s0, s1, s2, a[6], a[8]);
-	MONT_MAC(t0, t1, t2, a[7], a[7]);
-	MONT_MUL(v0, v1, v2, u[0], m[14]);
-	MONT_MUL(w0, w1, w2, u[1], m[13]);
-	MONT_MAC(t0, t1, t2, u[2], m[12]);
-	MONT_MAC(v0, v1, v2, u[3], m[11]);
-	MONT_MAC(w0, w1, w2, u[4], m[10]);
-	MONT_MAC(t0, t1, t2, u[5], m[9]);
-	MONT_MAC(v0, v1, v2, u[6], m[8]);
-	MONT_MAC(w0, w1, w2, u[7], m[7]);
-	MONT_MAC(t0, t1, t2, u[8], m[6]);
-	MONT_MAC(v0, v1, v2, u[9], m[5]);
-	MONT_MAC(w0, w1, w2, u[10], m[4]);
-	MONT_MAC(t0, t1, t2, u[11], m[3]);
-	MONT_MAC(v0, v1, v2, u[12], m[2]);
-	MONT_MAC(w0, w1, w2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MUL(s0, s1, s2, a[0], a[15]);
-	MONT_MUL(c0, c1, c2, a[1], a[14]);
-	MONT_MAC(s0, s1, s2, a[2], a[13]);
-	MONT_MAC(c0, c1, c2, a[3], a[12]);
-	MONT_MAC(s0, s1, s2, a[4], a[11]);
-	MONT_MAC(c0, c1, c2, a[5], a[10]);
-	MONT_MAC(s0, s1, s2, a[6], a[9]);
-	MONT_MAC(c0, c1, c2, a[7], a[8]);
-	MONT_MAC(t0, t1, t2, u[0], m[15]);
-	MONT_MUL(v0, v1, v2, u[1], m[14]);
-	MONT_MUL(w0, w1, w2, u[2], m[13]);
-	MONT_MAC(t0, t1, t2, u[3], m[12]);
-	MONT_MAC(v0, v1, v2, u[4], m[11]);
-	MONT_MAC(w0, w1, w2, u[5], m[10]);
-	MONT_MAC(t0, t1, t2, u[6], m[9]);
-	MONT_MAC(v0, v1, v2, u[7], m[8]);
-	MONT_MAC(w0, w1, w2, u[8], m[7]);
-	MONT_MAC(t0, t1, t2, u[9], m[6]);
-	MONT_MAC(v0, v1, v2, u[10], m[5]);
-	MONT_MAC(w0, w1, w2, u[11], m[4]);
-	MONT_MAC(t0, t1, t2, u[12], m[3]);
-	MONT_MAC(v0, v1, v2, u[13], m[2]);
-	MONT_MAC(w0, w1, w2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MUL(s0, s1, s2, a[1], a[15]);
-	MONT_MUL(c0, c1, c2, a[2], a[14]);
-	MONT_MAC(s0, s1, s2, a[3], a[13]);
-	MONT_MAC(c0, c1, c2, a[4], a[12]);
-	MONT_MAC(s0, s1, s2, a[5], a[11]);
-	MONT_MAC(c0, c1, c2, a[6], a[10]);
-	MONT_MAC(s0, s1, s2, a[7], a[9]);
-	MONT_MAC(t0, t1, t2, a[8], a[8]);
-	MONT_MUL(v0, v1, v2, u[1], m[15]);
-	MONT_MUL(w0, w1, w2, u[2], m[14]);
-	MONT_MAC(t0, t1, t2, u[3], m[13]);
-	MONT_MAC(v0, v1, v2, u[4], m[12]);
-	MONT_MAC(w0, w1, w2, u[5], m[11]);
-	MONT_MAC(t0, t1, t2, u[6], m[10]);
-	MONT_MAC(v0, v1, v2, u[7], m[9]);
-	MONT_MAC(w0, w1, w2, u[8], m[8]);
-	MONT_MAC(t0, t1, t2, u[9], m[7]);
-	MONT_MAC(v0, v1, v2, u[10], m[6]);
-	MONT_MAC(w0, w1, w2, u[11], m[5]);
-	MONT_MAC(t0, t1, t2, u[12], m[4]);
-	MONT_MAC(v0, v1, v2, u[13], m[3]);
-	MONT_MAC(w0, w1, w2, u[14], m[2]);
-	MONT_MAC(t0, t1, t2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MUL(s0, s1, s2, a[2], a[15]);
-	MONT_MUL(c0, c1, c2, a[3], a[14]);
-	MONT_MAC(s0, s1, s2, a[4], a[13]);
-	MONT_MAC(c0, c1, c2, a[5], a[12]);
-	MONT_MAC(s0, s1, s2, a[6], a[11]);
-	MONT_MAC(c0, c1, c2, a[7], a[10]);
-	MONT_MAC(s0, s1, s2, a[8], a[9]);
-	MONT_MAC(t0, t1, t2, u[2], m[15]);
-	MONT_MUL(v0, v1, v2, u[3], m[14]);
-	MONT_MUL(w0, w1, w2, u[4], m[13]);
-	MONT_MAC(t0, t1, t2, u[5], m[12]);
-	MONT_MAC(v0, v1, v2, u[6], m[11]);
-	MONT_MAC(w0, w1, w2, u[7], m[10]);
-	MONT_MAC(t0, t1, t2, u[8], m[9]);
-	MONT_MAC(v0, v1, v2, u[9], m[8]);
-	MONT_MAC(w0, w1, w2, u[10], m[7]);
-	MONT_MAC(t0, t1, t2, u[11], m[6]);
-	MONT_MAC(v0, v1, v2, u[12], m[5]);
-	MONT_MAC(w0, w1, w2, u[13], m[4]);
-	MONT_MAC(t0, t1, t2, u[14], m[3]);
-	MONT_MAC(v0, v1, v2, u[15], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MUL(s0, s1, s2, a[3], a[15]);
-	MONT_MUL(c0, c1, c2, a[4], a[14]);
-	MONT_MAC(s0, s1, s2, a[5], a[13]);
-	MONT_MAC(c0, c1, c2, a[6], a[12]);
-	MONT_MAC(s0, s1, s2, a[7], a[11]);
-	MONT_MAC(c0, c1, c2, a[8], a[10]);
-	MONT_MAC(t0, t1, t2, a[9], a[9]);
-	MONT_MUL(v0, v1, v2, u[3], m[15]);
-	MONT_MUL(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MUL(s0, s1, s2, a[4], a[15]);
-	MONT_MUL(c0, c1, c2, a[5], a[14]);
-	MONT_MAC(s0, s1, s2, a[6], a[13]);
-	MONT_MAC(c0, c1, c2, a[7], a[12]);
-	MONT_MAC(s0, s1, s2, a[8], a[11]);
-	MONT_MAC(c0, c1, c2, a[9], a[10]);
-	MONT_MAC(t0, t1, t2, u[4], m[15]);
-	MONT_MUL(v0, v1, v2, u[5], m[14]);
-	MONT_MUL(w0, w1, w2, u[6], m[13]);
-	MONT_MAC(t0, t1, t2, u[7], m[12]);
-	MONT_MAC(v0, v1, v2, u[8], m[11]);
-	MONT_MAC(w0, w1, w2, u[9], m[10]);
-	MONT_MAC(t0, t1, t2, u[10], m[9]);
-	MONT_MAC(v0, v1, v2, u[11], m[8]);
-	MONT_MAC(w0, w1, w2, u[12], m[7]);
-	MONT_MAC(t0, t1, t2, u[13], m[6]);
-	MONT_MAC(v0, v1, v2, u[14], m[5]);
-	MONT_MAC(w0, w1, w2, u[15], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MUL(s0, s1, s2, a[5], a[15]);
-	MONT_MUL(c0, c1, c2, a[6], a[14]);
-	MONT_MAC(s0, s1, s2, a[7], a[13]);
-	MONT_MAC(c0, c1, c2, a[8], a[12]);
-	MONT_MAC(s0, s1, s2, a[9], a[11]);
-	MONT_MAC(t0, t1, t2, a[10], a[10]);
-	MONT_MUL(v0, v1, v2, u[5], m[15]);
-	MONT_MUL(w0, w1, w2, u[6], m[14]);
-	MONT_MAC(t0, t1, t2, u[7], m[13]);
-	MONT_MAC(v0, v1, v2, u[8], m[12]);
-	MONT_MAC(w0, w1, w2, u[9], m[11]);
-	MONT_MAC(t0, t1, t2, u[10], m[10]);
-	MONT_MAC(v0, v1, v2, u[11], m[9]);
-	MONT_MAC(w0, w1, w2, u[12], m[8]);
-	MONT_MAC(t0, t1, t2, u[13], m[7]);
-	MONT_MAC(v0, v1, v2, u[14], m[6]);
-	MONT_MAC(w0, w1, w2, u[15], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MUL(s0, s1, s2, a[6], a[15]);
-	MONT_MUL(c0, c1, c2, a[7], a[14]);
-	MONT_MAC(s0, s1, s2, a[8], a[13]);
-	MONT_MAC(c0, c1, c2, a[9], a[12]);
-	MONT_MAC(s0, s1, s2, a[10], a[11]);
-	MONT_MAC(t0, t1, t2, u[6], m[15]);
-	MONT_MUL(v0, v1, v2, u[7], m[14]);
-	MONT_MUL(w0, w1, w2, u[8], m[13]);
-	MONT_MAC(t0, t1, t2, u[9], m[12]);
-	MONT_MAC(v0, v1, v2, u[10], m[11]);
-	MONT_MAC(w0, w1, w2, u[11], m[10]);
-	MONT_MAC(t0, t1, t2, u[12], m[9]);
-	MONT_MAC(v0, v1, v2, u[13], m[8]);
-	MONT_MAC(w0, w1, w2, u[14], m[7]);
-	MONT_MAC(t0, t1, t2, u[15], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MUL(s0, s1, s2, a[7], a[15]);
-	MONT_MUL(c0, c1, c2, a[8], a[14]);
-	MONT_MAC(s0, s1, s2, a[9], a[13]);
-	MONT_MAC(c0, c1, c2, a[10], a[12]);
-	MONT_MAC(t0, t1, t2, a[11], a[11]);
-	MONT_MUL(v0, v1, v2, u[7], m[15]);
-	MONT_MUL(w0, w1, w2, u[8], m[14]);
-	MONT_MAC(t0, t1, t2, u[9], m[13]);
-	MONT_MAC(v0, v1, v2, u[10], m[12]);
-	MONT_MAC(w0, w1, w2, u[11], m[11]);
-	MONT_MAC(t0, t1, t2, u[12], m[10]);
-	MONT_MAC(v0, v1, v2, u[13], m[9]);
-	MONT_MAC(w0, w1, w2, u[14], m[8]);
-	MONT_MAC(t0, t1, t2, u[15], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MUL(s0, s1, s2, a[8], a[15]);
-	MONT_MUL(c0, c1, c2, a[9], a[14]);
-	MONT_MAC(s0, s1, s2, a[10], a[13]);
-	MONT_MAC(c0, c1, c2, a[11], a[12]);
-	MONT_MAC(t0, t1, t2, u[8], m[15]);
-	MONT_MUL(v0, v1, v2, u[9], m[14]);
-	MONT_MUL(w0, w1, w2, u[10], m[13]);
-	MONT_MAC(t0, t1, t2, u[11], m[12]);
-	MONT_MAC(v0, v1, v2, u[12], m[11]);
-	MONT_MAC(w0, w1, w2, u[13], m[10]);
-	MONT_MAC(t0, t1, t2, u[14], m[9]);
-	MONT_MAC(v0, v1, v2, u[15], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MUL(s0, s1, s2, a[9], a[15]);
-	MONT_MUL(c0, c1, c2, a[10], a[14]);
-	MONT_MAC(s0, s1, s2, a[11], a[13]);
-	MONT_MAC(t0, t1, t2, a[12], a[12]);
-	MONT_MUL(v0, v1, v2, u[9], m[15]);
-	MONT_MUL(w0, w1, w2, u[10], m[14]);
-	MONT_MAC(t0, t1, t2, u[11], m[13]);
-	MONT_MAC(v0, v1, v2, u[12], m[12]);
-	MONT_MAC(w0, w1, w2, u[13], m[11]);
-	MONT_MAC(t0, t1, t2, u[14], m[10]);
-	MONT_MAC(v0, v1, v2, u[15], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MUL(s0, s1, s2, a[10], a[15]);
-	MONT_MUL(c0, c1, c2, a[11], a[14]);
-	MONT_MAC(s0, s1, s2, a[12], a[13]);
-	MONT_MAC(t0, t1, t2, u[10], m[15]);
-	MONT_MUL(v0, v1, v2, u[11], m[14]);
-	MONT_MUL(w0, w1, w2, u[12], m[13]);
-	MONT_MAC(t0, t1, t2, u[13], m[12]);
-	MONT_MAC(v0, v1, v2, u[14], m[11]);
-	MONT_MAC(w0, w1, w2, u[15], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MUL(s0, s1, s2, a[11], a[15]);
-	MONT_MUL(c0, c1, c2, a[12], a[14]);
-	MONT_MAC(t0, t1, t2, a[13], a[13]);
-	MONT_MUL(v0, v1, v2, u[11], m[15]);
-	MONT_MUL(w0, w1, w2, u[12], m[14]);
-	MONT_MAC(t0, t1, t2, u[13], m[13]);
-	MONT_MAC(v0, v1, v2, u[14], m[12]);
-	MONT_MAC(w0, w1, w2, u[15], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MUL(s0, s1, s2, a[12], a[15]);
-	MONT_MUL(c0, c1, c2, a[13], a[14]);
-	MONT_MAC(t0, t1, t2, u[12], m[15]);
-	MONT_MUL(v0, v1, v2, u[13], m[14]);
-	MONT_MUL(w0, w1, w2, u[14], m[13]);
-	MONT_MAC(t0, t1, t2, u[15], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MUL(s0, s1, s2, a[13], a[15]);
-	MONT_MAC(t0, t1, t2, a[14], a[14]);
-	MONT_MUL(v0, v1, v2, u[13], m[15]);
-	MONT_MUL(w0, w1, w2, u[14], m[14]);
-	MONT_MAC(t0, t1, t2, u[15], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MUL(s0, s1, s2, a[14], a[15]);
-	MONT_MAC(t0, t1, t2, u[14], m[15]);
-	MONT_MUL(v0, v1, v2, u[15], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MAC(t0, t1, t2, a[15], a[15]);
-	MONT_MUL(v0, v1, v2, u[15], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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 * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
-static void crypton_mont_mul24(limb_t *r, const limb_t *a, const limb_t *b,
-                               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, v0, v1, v2, w0, w1, w2, borrow, take;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], b[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MAC(t0, t1, t2, a[0], b[1]);
-	MONT_MUL(v0, v1, v2, a[1], b[0]);
-	MONT_MUL(w0, w1, w2, u[0], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MAC(t0, t1, t2, a[0], b[2]);
-	MONT_MUL(v0, v1, v2, a[1], b[1]);
-	MONT_MUL(w0, w1, w2, a[2], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[2]);
-	MONT_MAC(v0, v1, v2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MAC(t0, t1, t2, a[0], b[3]);
-	MONT_MUL(v0, v1, v2, a[1], b[2]);
-	MONT_MUL(w0, w1, w2, a[2], b[1]);
-	MONT_MAC(t0, t1, t2, a[3], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[3]);
-	MONT_MAC(w0, w1, w2, u[1], m[2]);
-	MONT_MAC(t0, t1, t2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MAC(t0, t1, t2, a[0], b[4]);
-	MONT_MUL(v0, v1, v2, a[1], b[3]);
-	MONT_MUL(w0, w1, w2, a[2], b[2]);
-	MONT_MAC(t0, t1, t2, a[3], b[1]);
-	MONT_MAC(v0, v1, v2, a[4], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[4]);
-	MONT_MAC(t0, t1, t2, u[1], m[3]);
-	MONT_MAC(v0, v1, v2, u[2], m[2]);
-	MONT_MAC(w0, w1, w2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MAC(t0, t1, t2, a[0], b[5]);
-	MONT_MUL(v0, v1, v2, a[1], b[4]);
-	MONT_MUL(w0, w1, w2, a[2], b[3]);
-	MONT_MAC(t0, t1, t2, a[3], b[2]);
-	MONT_MAC(v0, v1, v2, a[4], b[1]);
-	MONT_MAC(w0, w1, w2, a[5], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MAC(v0, v1, v2, u[1], m[4]);
-	MONT_MAC(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MAC(t0, t1, t2, a[0], b[6]);
-	MONT_MUL(v0, v1, v2, a[1], b[5]);
-	MONT_MUL(w0, w1, w2, a[2], b[4]);
-	MONT_MAC(t0, t1, t2, a[3], b[3]);
-	MONT_MAC(v0, v1, v2, a[4], b[2]);
-	MONT_MAC(w0, w1, w2, a[5], b[1]);
-	MONT_MAC(t0, t1, t2, a[6], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[6]);
-	MONT_MAC(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MAC(t0, t1, t2, a[0], b[7]);
-	MONT_MUL(v0, v1, v2, a[1], b[6]);
-	MONT_MUL(w0, w1, w2, a[2], b[5]);
-	MONT_MAC(t0, t1, t2, a[3], b[4]);
-	MONT_MAC(v0, v1, v2, a[4], b[3]);
-	MONT_MAC(w0, w1, w2, a[5], b[2]);
-	MONT_MAC(t0, t1, t2, a[6], b[1]);
-	MONT_MAC(v0, v1, v2, a[7], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[7]);
-	MONT_MAC(t0, t1, t2, u[1], m[6]);
-	MONT_MAC(v0, v1, v2, u[2], m[5]);
-	MONT_MAC(w0, w1, w2, u[3], m[4]);
-	MONT_MAC(t0, t1, t2, u[4], m[3]);
-	MONT_MAC(v0, v1, v2, u[5], m[2]);
-	MONT_MAC(w0, w1, w2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MAC(t0, t1, t2, a[0], b[8]);
-	MONT_MUL(v0, v1, v2, a[1], b[7]);
-	MONT_MUL(w0, w1, w2, a[2], b[6]);
-	MONT_MAC(t0, t1, t2, a[3], b[5]);
-	MONT_MAC(v0, v1, v2, a[4], b[4]);
-	MONT_MAC(w0, w1, w2, a[5], b[3]);
-	MONT_MAC(t0, t1, t2, a[6], b[2]);
-	MONT_MAC(v0, v1, v2, a[7], b[1]);
-	MONT_MAC(w0, w1, w2, a[8], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[8]);
-	MONT_MAC(v0, v1, v2, u[1], m[7]);
-	MONT_MAC(w0, w1, w2, u[2], m[6]);
-	MONT_MAC(t0, t1, t2, u[3], m[5]);
-	MONT_MAC(v0, v1, v2, u[4], m[4]);
-	MONT_MAC(w0, w1, w2, u[5], m[3]);
-	MONT_MAC(t0, t1, t2, u[6], m[2]);
-	MONT_MAC(v0, v1, v2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MAC(t0, t1, t2, a[0], b[9]);
-	MONT_MUL(v0, v1, v2, a[1], b[8]);
-	MONT_MUL(w0, w1, w2, a[2], b[7]);
-	MONT_MAC(t0, t1, t2, a[3], b[6]);
-	MONT_MAC(v0, v1, v2, a[4], b[5]);
-	MONT_MAC(w0, w1, w2, a[5], b[4]);
-	MONT_MAC(t0, t1, t2, a[6], b[3]);
-	MONT_MAC(v0, v1, v2, a[7], b[2]);
-	MONT_MAC(w0, w1, w2, a[8], b[1]);
-	MONT_MAC(t0, t1, t2, a[9], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[9]);
-	MONT_MAC(w0, w1, w2, u[1], m[8]);
-	MONT_MAC(t0, t1, t2, u[2], m[7]);
-	MONT_MAC(v0, v1, v2, u[3], m[6]);
-	MONT_MAC(w0, w1, w2, u[4], m[5]);
-	MONT_MAC(t0, t1, t2, u[5], m[4]);
-	MONT_MAC(v0, v1, v2, u[6], m[3]);
-	MONT_MAC(w0, w1, w2, u[7], m[2]);
-	MONT_MAC(t0, t1, t2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MAC(t0, t1, t2, a[0], b[10]);
-	MONT_MUL(v0, v1, v2, a[1], b[9]);
-	MONT_MUL(w0, w1, w2, a[2], b[8]);
-	MONT_MAC(t0, t1, t2, a[3], b[7]);
-	MONT_MAC(v0, v1, v2, a[4], b[6]);
-	MONT_MAC(w0, w1, w2, a[5], b[5]);
-	MONT_MAC(t0, t1, t2, a[6], b[4]);
-	MONT_MAC(v0, v1, v2, a[7], b[3]);
-	MONT_MAC(w0, w1, w2, a[8], b[2]);
-	MONT_MAC(t0, t1, t2, a[9], b[1]);
-	MONT_MAC(v0, v1, v2, a[10], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[10]);
-	MONT_MAC(t0, t1, t2, u[1], m[9]);
-	MONT_MAC(v0, v1, v2, u[2], m[8]);
-	MONT_MAC(w0, w1, w2, u[3], m[7]);
-	MONT_MAC(t0, t1, t2, u[4], m[6]);
-	MONT_MAC(v0, v1, v2, u[5], m[5]);
-	MONT_MAC(w0, w1, w2, u[6], m[4]);
-	MONT_MAC(t0, t1, t2, u[7], m[3]);
-	MONT_MAC(v0, v1, v2, u[8], m[2]);
-	MONT_MAC(w0, w1, w2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MAC(t0, t1, t2, a[0], b[11]);
-	MONT_MUL(v0, v1, v2, a[1], b[10]);
-	MONT_MUL(w0, w1, w2, a[2], b[9]);
-	MONT_MAC(t0, t1, t2, a[3], b[8]);
-	MONT_MAC(v0, v1, v2, a[4], b[7]);
-	MONT_MAC(w0, w1, w2, a[5], b[6]);
-	MONT_MAC(t0, t1, t2, a[6], b[5]);
-	MONT_MAC(v0, v1, v2, a[7], b[4]);
-	MONT_MAC(w0, w1, w2, a[8], b[3]);
-	MONT_MAC(t0, t1, t2, a[9], b[2]);
-	MONT_MAC(v0, v1, v2, a[10], b[1]);
-	MONT_MAC(w0, w1, w2, a[11], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MAC(v0, v1, v2, u[1], m[10]);
-	MONT_MAC(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MAC(t0, t1, t2, a[0], b[12]);
-	MONT_MUL(v0, v1, v2, a[1], b[11]);
-	MONT_MUL(w0, w1, w2, a[2], b[10]);
-	MONT_MAC(t0, t1, t2, a[3], b[9]);
-	MONT_MAC(v0, v1, v2, a[4], b[8]);
-	MONT_MAC(w0, w1, w2, a[5], b[7]);
-	MONT_MAC(t0, t1, t2, a[6], b[6]);
-	MONT_MAC(v0, v1, v2, a[7], b[5]);
-	MONT_MAC(w0, w1, w2, a[8], b[4]);
-	MONT_MAC(t0, t1, t2, a[9], b[3]);
-	MONT_MAC(v0, v1, v2, a[10], b[2]);
-	MONT_MAC(w0, w1, w2, a[11], b[1]);
-	MONT_MAC(t0, t1, t2, a[12], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[12]);
-	MONT_MAC(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MAC(t0, t1, t2, a[0], b[13]);
-	MONT_MUL(v0, v1, v2, a[1], b[12]);
-	MONT_MUL(w0, w1, w2, a[2], b[11]);
-	MONT_MAC(t0, t1, t2, a[3], b[10]);
-	MONT_MAC(v0, v1, v2, a[4], b[9]);
-	MONT_MAC(w0, w1, w2, a[5], b[8]);
-	MONT_MAC(t0, t1, t2, a[6], b[7]);
-	MONT_MAC(v0, v1, v2, a[7], b[6]);
-	MONT_MAC(w0, w1, w2, a[8], b[5]);
-	MONT_MAC(t0, t1, t2, a[9], b[4]);
-	MONT_MAC(v0, v1, v2, a[10], b[3]);
-	MONT_MAC(w0, w1, w2, a[11], b[2]);
-	MONT_MAC(t0, t1, t2, a[12], b[1]);
-	MONT_MAC(v0, v1, v2, a[13], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[13]);
-	MONT_MAC(t0, t1, t2, u[1], m[12]);
-	MONT_MAC(v0, v1, v2, u[2], m[11]);
-	MONT_MAC(w0, w1, w2, u[3], m[10]);
-	MONT_MAC(t0, t1, t2, u[4], m[9]);
-	MONT_MAC(v0, v1, v2, u[5], m[8]);
-	MONT_MAC(w0, w1, w2, u[6], m[7]);
-	MONT_MAC(t0, t1, t2, u[7], m[6]);
-	MONT_MAC(v0, v1, v2, u[8], m[5]);
-	MONT_MAC(w0, w1, w2, u[9], m[4]);
-	MONT_MAC(t0, t1, t2, u[10], m[3]);
-	MONT_MAC(v0, v1, v2, u[11], m[2]);
-	MONT_MAC(w0, w1, w2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MAC(t0, t1, t2, a[0], b[14]);
-	MONT_MUL(v0, v1, v2, a[1], b[13]);
-	MONT_MUL(w0, w1, w2, a[2], b[12]);
-	MONT_MAC(t0, t1, t2, a[3], b[11]);
-	MONT_MAC(v0, v1, v2, a[4], b[10]);
-	MONT_MAC(w0, w1, w2, a[5], b[9]);
-	MONT_MAC(t0, t1, t2, a[6], b[8]);
-	MONT_MAC(v0, v1, v2, a[7], b[7]);
-	MONT_MAC(w0, w1, w2, a[8], b[6]);
-	MONT_MAC(t0, t1, t2, a[9], b[5]);
-	MONT_MAC(v0, v1, v2, a[10], b[4]);
-	MONT_MAC(w0, w1, w2, a[11], b[3]);
-	MONT_MAC(t0, t1, t2, a[12], b[2]);
-	MONT_MAC(v0, v1, v2, a[13], b[1]);
-	MONT_MAC(w0, w1, w2, a[14], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[14]);
-	MONT_MAC(v0, v1, v2, u[1], m[13]);
-	MONT_MAC(w0, w1, w2, u[2], m[12]);
-	MONT_MAC(t0, t1, t2, u[3], m[11]);
-	MONT_MAC(v0, v1, v2, u[4], m[10]);
-	MONT_MAC(w0, w1, w2, u[5], m[9]);
-	MONT_MAC(t0, t1, t2, u[6], m[8]);
-	MONT_MAC(v0, v1, v2, u[7], m[7]);
-	MONT_MAC(w0, w1, w2, u[8], m[6]);
-	MONT_MAC(t0, t1, t2, u[9], m[5]);
-	MONT_MAC(v0, v1, v2, u[10], m[4]);
-	MONT_MAC(w0, w1, w2, u[11], m[3]);
-	MONT_MAC(t0, t1, t2, u[12], m[2]);
-	MONT_MAC(v0, v1, v2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MAC(t0, t1, t2, a[0], b[15]);
-	MONT_MUL(v0, v1, v2, a[1], b[14]);
-	MONT_MUL(w0, w1, w2, a[2], b[13]);
-	MONT_MAC(t0, t1, t2, a[3], b[12]);
-	MONT_MAC(v0, v1, v2, a[4], b[11]);
-	MONT_MAC(w0, w1, w2, a[5], b[10]);
-	MONT_MAC(t0, t1, t2, a[6], b[9]);
-	MONT_MAC(v0, v1, v2, a[7], b[8]);
-	MONT_MAC(w0, w1, w2, a[8], b[7]);
-	MONT_MAC(t0, t1, t2, a[9], b[6]);
-	MONT_MAC(v0, v1, v2, a[10], b[5]);
-	MONT_MAC(w0, w1, w2, a[11], b[4]);
-	MONT_MAC(t0, t1, t2, a[12], b[3]);
-	MONT_MAC(v0, v1, v2, a[13], b[2]);
-	MONT_MAC(w0, w1, w2, a[14], b[1]);
-	MONT_MAC(t0, t1, t2, a[15], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[15]);
-	MONT_MAC(w0, w1, w2, u[1], m[14]);
-	MONT_MAC(t0, t1, t2, u[2], m[13]);
-	MONT_MAC(v0, v1, v2, u[3], m[12]);
-	MONT_MAC(w0, w1, w2, u[4], m[11]);
-	MONT_MAC(t0, t1, t2, u[5], m[10]);
-	MONT_MAC(v0, v1, v2, u[6], m[9]);
-	MONT_MAC(w0, w1, w2, u[7], m[8]);
-	MONT_MAC(t0, t1, t2, u[8], m[7]);
-	MONT_MAC(v0, v1, v2, u[9], m[6]);
-	MONT_MAC(w0, w1, w2, u[10], m[5]);
-	MONT_MAC(t0, t1, t2, u[11], m[4]);
-	MONT_MAC(v0, v1, v2, u[12], m[3]);
-	MONT_MAC(w0, w1, w2, u[13], m[2]);
-	MONT_MAC(t0, t1, t2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MAC(t0, t1, t2, a[0], b[16]);
-	MONT_MUL(v0, v1, v2, a[1], b[15]);
-	MONT_MUL(w0, w1, w2, a[2], b[14]);
-	MONT_MAC(t0, t1, t2, a[3], b[13]);
-	MONT_MAC(v0, v1, v2, a[4], b[12]);
-	MONT_MAC(w0, w1, w2, a[5], b[11]);
-	MONT_MAC(t0, t1, t2, a[6], b[10]);
-	MONT_MAC(v0, v1, v2, a[7], b[9]);
-	MONT_MAC(w0, w1, w2, a[8], b[8]);
-	MONT_MAC(t0, t1, t2, a[9], b[7]);
-	MONT_MAC(v0, v1, v2, a[10], b[6]);
-	MONT_MAC(w0, w1, w2, a[11], b[5]);
-	MONT_MAC(t0, t1, t2, a[12], b[4]);
-	MONT_MAC(v0, v1, v2, a[13], b[3]);
-	MONT_MAC(w0, w1, w2, a[14], b[2]);
-	MONT_MAC(t0, t1, t2, a[15], b[1]);
-	MONT_MAC(v0, v1, v2, a[16], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[16]);
-	MONT_MAC(t0, t1, t2, u[1], m[15]);
-	MONT_MAC(v0, v1, v2, u[2], m[14]);
-	MONT_MAC(w0, w1, w2, u[3], m[13]);
-	MONT_MAC(t0, t1, t2, u[4], m[12]);
-	MONT_MAC(v0, v1, v2, u[5], m[11]);
-	MONT_MAC(w0, w1, w2, u[6], m[10]);
-	MONT_MAC(t0, t1, t2, u[7], m[9]);
-	MONT_MAC(v0, v1, v2, u[8], m[8]);
-	MONT_MAC(w0, w1, w2, u[9], m[7]);
-	MONT_MAC(t0, t1, t2, u[10], m[6]);
-	MONT_MAC(v0, v1, v2, u[11], m[5]);
-	MONT_MAC(w0, w1, w2, u[12], m[4]);
-	MONT_MAC(t0, t1, t2, u[13], m[3]);
-	MONT_MAC(v0, v1, v2, u[14], m[2]);
-	MONT_MAC(w0, w1, w2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[16] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[16], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MAC(t0, t1, t2, a[0], b[17]);
-	MONT_MUL(v0, v1, v2, a[1], b[16]);
-	MONT_MUL(w0, w1, w2, a[2], b[15]);
-	MONT_MAC(t0, t1, t2, a[3], b[14]);
-	MONT_MAC(v0, v1, v2, a[4], b[13]);
-	MONT_MAC(w0, w1, w2, a[5], b[12]);
-	MONT_MAC(t0, t1, t2, a[6], b[11]);
-	MONT_MAC(v0, v1, v2, a[7], b[10]);
-	MONT_MAC(w0, w1, w2, a[8], b[9]);
-	MONT_MAC(t0, t1, t2, a[9], b[8]);
-	MONT_MAC(v0, v1, v2, a[10], b[7]);
-	MONT_MAC(w0, w1, w2, a[11], b[6]);
-	MONT_MAC(t0, t1, t2, a[12], b[5]);
-	MONT_MAC(v0, v1, v2, a[13], b[4]);
-	MONT_MAC(w0, w1, w2, a[14], b[3]);
-	MONT_MAC(t0, t1, t2, a[15], b[2]);
-	MONT_MAC(v0, v1, v2, a[16], b[1]);
-	MONT_MAC(w0, w1, w2, a[17], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[17]);
-	MONT_MAC(v0, v1, v2, u[1], m[16]);
-	MONT_MAC(w0, w1, w2, u[2], m[15]);
-	MONT_MAC(t0, t1, t2, u[3], m[14]);
-	MONT_MAC(v0, v1, v2, u[4], m[13]);
-	MONT_MAC(w0, w1, w2, u[5], m[12]);
-	MONT_MAC(t0, t1, t2, u[6], m[11]);
-	MONT_MAC(v0, v1, v2, u[7], m[10]);
-	MONT_MAC(w0, w1, w2, u[8], m[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[8]);
-	MONT_MAC(v0, v1, v2, u[10], m[7]);
-	MONT_MAC(w0, w1, w2, u[11], m[6]);
-	MONT_MAC(t0, t1, t2, u[12], m[5]);
-	MONT_MAC(v0, v1, v2, u[13], m[4]);
-	MONT_MAC(w0, w1, w2, u[14], m[3]);
-	MONT_MAC(t0, t1, t2, u[15], m[2]);
-	MONT_MAC(v0, v1, v2, u[16], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[17] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[17], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MAC(t0, t1, t2, a[0], b[18]);
-	MONT_MUL(v0, v1, v2, a[1], b[17]);
-	MONT_MUL(w0, w1, w2, a[2], b[16]);
-	MONT_MAC(t0, t1, t2, a[3], b[15]);
-	MONT_MAC(v0, v1, v2, a[4], b[14]);
-	MONT_MAC(w0, w1, w2, a[5], b[13]);
-	MONT_MAC(t0, t1, t2, a[6], b[12]);
-	MONT_MAC(v0, v1, v2, a[7], b[11]);
-	MONT_MAC(w0, w1, w2, a[8], b[10]);
-	MONT_MAC(t0, t1, t2, a[9], b[9]);
-	MONT_MAC(v0, v1, v2, a[10], b[8]);
-	MONT_MAC(w0, w1, w2, a[11], b[7]);
-	MONT_MAC(t0, t1, t2, a[12], b[6]);
-	MONT_MAC(v0, v1, v2, a[13], b[5]);
-	MONT_MAC(w0, w1, w2, a[14], b[4]);
-	MONT_MAC(t0, t1, t2, a[15], b[3]);
-	MONT_MAC(v0, v1, v2, a[16], b[2]);
-	MONT_MAC(w0, w1, w2, a[17], b[1]);
-	MONT_MAC(t0, t1, t2, a[18], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[18]);
-	MONT_MAC(w0, w1, w2, u[1], m[17]);
-	MONT_MAC(t0, t1, t2, u[2], m[16]);
-	MONT_MAC(v0, v1, v2, u[3], m[15]);
-	MONT_MAC(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_MAC(w0, w1, w2, u[16], m[2]);
-	MONT_MAC(t0, t1, t2, u[17], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[18] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[18], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MAC(t0, t1, t2, a[0], b[19]);
-	MONT_MUL(v0, v1, v2, a[1], b[18]);
-	MONT_MUL(w0, w1, w2, a[2], b[17]);
-	MONT_MAC(t0, t1, t2, a[3], b[16]);
-	MONT_MAC(v0, v1, v2, a[4], b[15]);
-	MONT_MAC(w0, w1, w2, a[5], b[14]);
-	MONT_MAC(t0, t1, t2, a[6], b[13]);
-	MONT_MAC(v0, v1, v2, a[7], b[12]);
-	MONT_MAC(w0, w1, w2, a[8], b[11]);
-	MONT_MAC(t0, t1, t2, a[9], b[10]);
-	MONT_MAC(v0, v1, v2, a[10], b[9]);
-	MONT_MAC(w0, w1, w2, a[11], b[8]);
-	MONT_MAC(t0, t1, t2, a[12], b[7]);
-	MONT_MAC(v0, v1, v2, a[13], b[6]);
-	MONT_MAC(w0, w1, w2, a[14], b[5]);
-	MONT_MAC(t0, t1, t2, a[15], b[4]);
-	MONT_MAC(v0, v1, v2, a[16], b[3]);
-	MONT_MAC(w0, w1, w2, a[17], b[2]);
-	MONT_MAC(t0, t1, t2, a[18], b[1]);
-	MONT_MAC(v0, v1, v2, a[19], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[19]);
-	MONT_MAC(t0, t1, t2, u[1], m[18]);
-	MONT_MAC(v0, v1, v2, u[2], m[17]);
-	MONT_MAC(w0, w1, w2, u[3], m[16]);
-	MONT_MAC(t0, t1, t2, u[4], m[15]);
-	MONT_MAC(v0, v1, v2, u[5], m[14]);
-	MONT_MAC(w0, w1, w2, u[6], m[13]);
-	MONT_MAC(t0, t1, t2, u[7], m[12]);
-	MONT_MAC(v0, v1, v2, u[8], m[11]);
-	MONT_MAC(w0, w1, w2, u[9], m[10]);
-	MONT_MAC(t0, t1, t2, u[10], m[9]);
-	MONT_MAC(v0, v1, v2, u[11], m[8]);
-	MONT_MAC(w0, w1, w2, u[12], m[7]);
-	MONT_MAC(t0, t1, t2, u[13], m[6]);
-	MONT_MAC(v0, v1, v2, u[14], m[5]);
-	MONT_MAC(w0, w1, w2, u[15], m[4]);
-	MONT_MAC(t0, t1, t2, u[16], m[3]);
-	MONT_MAC(v0, v1, v2, u[17], m[2]);
-	MONT_MAC(w0, w1, w2, u[18], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[19] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[19], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MAC(t0, t1, t2, a[0], b[20]);
-	MONT_MUL(v0, v1, v2, a[1], b[19]);
-	MONT_MUL(w0, w1, w2, a[2], b[18]);
-	MONT_MAC(t0, t1, t2, a[3], b[17]);
-	MONT_MAC(v0, v1, v2, a[4], b[16]);
-	MONT_MAC(w0, w1, w2, a[5], b[15]);
-	MONT_MAC(t0, t1, t2, a[6], b[14]);
-	MONT_MAC(v0, v1, v2, a[7], b[13]);
-	MONT_MAC(w0, w1, w2, a[8], b[12]);
-	MONT_MAC(t0, t1, t2, a[9], b[11]);
-	MONT_MAC(v0, v1, v2, a[10], b[10]);
-	MONT_MAC(w0, w1, w2, a[11], b[9]);
-	MONT_MAC(t0, t1, t2, a[12], b[8]);
-	MONT_MAC(v0, v1, v2, a[13], b[7]);
-	MONT_MAC(w0, w1, w2, a[14], b[6]);
-	MONT_MAC(t0, t1, t2, a[15], b[5]);
-	MONT_MAC(v0, v1, v2, a[16], b[4]);
-	MONT_MAC(w0, w1, w2, a[17], b[3]);
-	MONT_MAC(t0, t1, t2, a[18], b[2]);
-	MONT_MAC(v0, v1, v2, a[19], b[1]);
-	MONT_MAC(w0, w1, w2, a[20], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[20]);
-	MONT_MAC(v0, v1, v2, u[1], m[19]);
-	MONT_MAC(w0, w1, w2, u[2], m[18]);
-	MONT_MAC(t0, t1, t2, u[3], m[17]);
-	MONT_MAC(v0, v1, v2, u[4], m[16]);
-	MONT_MAC(w0, w1, w2, u[5], m[15]);
-	MONT_MAC(t0, t1, t2, u[6], m[14]);
-	MONT_MAC(v0, v1, v2, u[7], m[13]);
-	MONT_MAC(w0, w1, w2, u[8], m[12]);
-	MONT_MAC(t0, t1, t2, u[9], m[11]);
-	MONT_MAC(v0, v1, v2, u[10], m[10]);
-	MONT_MAC(w0, w1, w2, u[11], m[9]);
-	MONT_MAC(t0, t1, t2, u[12], m[8]);
-	MONT_MAC(v0, v1, v2, u[13], m[7]);
-	MONT_MAC(w0, w1, w2, u[14], m[6]);
-	MONT_MAC(t0, t1, t2, u[15], m[5]);
-	MONT_MAC(v0, v1, v2, u[16], m[4]);
-	MONT_MAC(w0, w1, w2, u[17], m[3]);
-	MONT_MAC(t0, t1, t2, u[18], m[2]);
-	MONT_MAC(v0, v1, v2, u[19], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[20] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[20], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MAC(t0, t1, t2, a[0], b[21]);
-	MONT_MUL(v0, v1, v2, a[1], b[20]);
-	MONT_MUL(w0, w1, w2, a[2], b[19]);
-	MONT_MAC(t0, t1, t2, a[3], b[18]);
-	MONT_MAC(v0, v1, v2, a[4], b[17]);
-	MONT_MAC(w0, w1, w2, a[5], b[16]);
-	MONT_MAC(t0, t1, t2, a[6], b[15]);
-	MONT_MAC(v0, v1, v2, a[7], b[14]);
-	MONT_MAC(w0, w1, w2, a[8], b[13]);
-	MONT_MAC(t0, t1, t2, a[9], b[12]);
-	MONT_MAC(v0, v1, v2, a[10], b[11]);
-	MONT_MAC(w0, w1, w2, a[11], b[10]);
-	MONT_MAC(t0, t1, t2, a[12], b[9]);
-	MONT_MAC(v0, v1, v2, a[13], b[8]);
-	MONT_MAC(w0, w1, w2, a[14], b[7]);
-	MONT_MAC(t0, t1, t2, a[15], b[6]);
-	MONT_MAC(v0, v1, v2, a[16], b[5]);
-	MONT_MAC(w0, w1, w2, a[17], b[4]);
-	MONT_MAC(t0, t1, t2, a[18], b[3]);
-	MONT_MAC(v0, v1, v2, a[19], b[2]);
-	MONT_MAC(w0, w1, w2, a[20], b[1]);
-	MONT_MAC(t0, t1, t2, a[21], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[21]);
-	MONT_MAC(w0, w1, w2, u[1], m[20]);
-	MONT_MAC(t0, t1, t2, u[2], m[19]);
-	MONT_MAC(v0, v1, v2, u[3], m[18]);
-	MONT_MAC(w0, w1, w2, u[4], m[17]);
-	MONT_MAC(t0, t1, t2, u[5], m[16]);
-	MONT_MAC(v0, v1, v2, u[6], m[15]);
-	MONT_MAC(w0, w1, w2, u[7], m[14]);
-	MONT_MAC(t0, t1, t2, u[8], m[13]);
-	MONT_MAC(v0, v1, v2, u[9], m[12]);
-	MONT_MAC(w0, w1, w2, u[10], m[11]);
-	MONT_MAC(t0, t1, t2, u[11], m[10]);
-	MONT_MAC(v0, v1, v2, u[12], m[9]);
-	MONT_MAC(w0, w1, w2, u[13], m[8]);
-	MONT_MAC(t0, t1, t2, u[14], m[7]);
-	MONT_MAC(v0, v1, v2, u[15], m[6]);
-	MONT_MAC(w0, w1, w2, u[16], m[5]);
-	MONT_MAC(t0, t1, t2, u[17], m[4]);
-	MONT_MAC(v0, v1, v2, u[18], m[3]);
-	MONT_MAC(w0, w1, w2, u[19], m[2]);
-	MONT_MAC(t0, t1, t2, u[20], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[21] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[21], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MAC(t0, t1, t2, a[0], b[22]);
-	MONT_MUL(v0, v1, v2, a[1], b[21]);
-	MONT_MUL(w0, w1, w2, a[2], b[20]);
-	MONT_MAC(t0, t1, t2, a[3], b[19]);
-	MONT_MAC(v0, v1, v2, a[4], b[18]);
-	MONT_MAC(w0, w1, w2, a[5], b[17]);
-	MONT_MAC(t0, t1, t2, a[6], b[16]);
-	MONT_MAC(v0, v1, v2, a[7], b[15]);
-	MONT_MAC(w0, w1, w2, a[8], b[14]);
-	MONT_MAC(t0, t1, t2, a[9], b[13]);
-	MONT_MAC(v0, v1, v2, a[10], b[12]);
-	MONT_MAC(w0, w1, w2, a[11], b[11]);
-	MONT_MAC(t0, t1, t2, a[12], b[10]);
-	MONT_MAC(v0, v1, v2, a[13], b[9]);
-	MONT_MAC(w0, w1, w2, a[14], b[8]);
-	MONT_MAC(t0, t1, t2, a[15], b[7]);
-	MONT_MAC(v0, v1, v2, a[16], b[6]);
-	MONT_MAC(w0, w1, w2, a[17], b[5]);
-	MONT_MAC(t0, t1, t2, a[18], b[4]);
-	MONT_MAC(v0, v1, v2, a[19], b[3]);
-	MONT_MAC(w0, w1, w2, a[20], b[2]);
-	MONT_MAC(t0, t1, t2, a[21], b[1]);
-	MONT_MAC(v0, v1, v2, a[22], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[22]);
-	MONT_MAC(t0, t1, t2, u[1], m[21]);
-	MONT_MAC(v0, v1, v2, u[2], m[20]);
-	MONT_MAC(w0, w1, w2, u[3], m[19]);
-	MONT_MAC(t0, t1, t2, u[4], m[18]);
-	MONT_MAC(v0, v1, v2, u[5], m[17]);
-	MONT_MAC(w0, w1, w2, u[6], m[16]);
-	MONT_MAC(t0, t1, t2, u[7], m[15]);
-	MONT_MAC(v0, v1, v2, u[8], m[14]);
-	MONT_MAC(w0, w1, w2, u[9], m[13]);
-	MONT_MAC(t0, t1, t2, u[10], m[12]);
-	MONT_MAC(v0, v1, v2, u[11], m[11]);
-	MONT_MAC(w0, w1, w2, u[12], m[10]);
-	MONT_MAC(t0, t1, t2, u[13], m[9]);
-	MONT_MAC(v0, v1, v2, u[14], m[8]);
-	MONT_MAC(w0, w1, w2, u[15], m[7]);
-	MONT_MAC(t0, t1, t2, u[16], m[6]);
-	MONT_MAC(v0, v1, v2, u[17], m[5]);
-	MONT_MAC(w0, w1, w2, u[18], m[4]);
-	MONT_MAC(t0, t1, t2, u[19], m[3]);
-	MONT_MAC(v0, v1, v2, u[20], m[2]);
-	MONT_MAC(w0, w1, w2, u[21], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[22] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[22], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MAC(t0, t1, t2, a[0], b[23]);
-	MONT_MUL(v0, v1, v2, a[1], b[22]);
-	MONT_MUL(w0, w1, w2, a[2], b[21]);
-	MONT_MAC(t0, t1, t2, a[3], b[20]);
-	MONT_MAC(v0, v1, v2, a[4], b[19]);
-	MONT_MAC(w0, w1, w2, a[5], b[18]);
-	MONT_MAC(t0, t1, t2, a[6], b[17]);
-	MONT_MAC(v0, v1, v2, a[7], b[16]);
-	MONT_MAC(w0, w1, w2, a[8], b[15]);
-	MONT_MAC(t0, t1, t2, a[9], b[14]);
-	MONT_MAC(v0, v1, v2, a[10], b[13]);
-	MONT_MAC(w0, w1, w2, a[11], b[12]);
-	MONT_MAC(t0, t1, t2, a[12], b[11]);
-	MONT_MAC(v0, v1, v2, a[13], b[10]);
-	MONT_MAC(w0, w1, w2, a[14], b[9]);
-	MONT_MAC(t0, t1, t2, a[15], b[8]);
-	MONT_MAC(v0, v1, v2, a[16], b[7]);
-	MONT_MAC(w0, w1, w2, a[17], b[6]);
-	MONT_MAC(t0, t1, t2, a[18], b[5]);
-	MONT_MAC(v0, v1, v2, a[19], b[4]);
-	MONT_MAC(w0, w1, w2, a[20], b[3]);
-	MONT_MAC(t0, t1, t2, a[21], b[2]);
-	MONT_MAC(v0, v1, v2, a[22], b[1]);
-	MONT_MAC(w0, w1, w2, a[23], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[23]);
-	MONT_MAC(v0, v1, v2, u[1], m[22]);
-	MONT_MAC(w0, w1, w2, u[2], m[21]);
-	MONT_MAC(t0, t1, t2, u[3], m[20]);
-	MONT_MAC(v0, v1, v2, u[4], m[19]);
-	MONT_MAC(w0, w1, w2, u[5], m[18]);
-	MONT_MAC(t0, t1, t2, u[6], m[17]);
-	MONT_MAC(v0, v1, v2, u[7], m[16]);
-	MONT_MAC(w0, w1, w2, u[8], m[15]);
-	MONT_MAC(t0, t1, t2, u[9], m[14]);
-	MONT_MAC(v0, v1, v2, u[10], m[13]);
-	MONT_MAC(w0, w1, w2, u[11], m[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[11]);
-	MONT_MAC(v0, v1, v2, u[13], m[10]);
-	MONT_MAC(w0, w1, w2, u[14], m[9]);
-	MONT_MAC(t0, t1, t2, u[15], m[8]);
-	MONT_MAC(v0, v1, v2, u[16], m[7]);
-	MONT_MAC(w0, w1, w2, u[17], m[6]);
-	MONT_MAC(t0, t1, t2, u[18], m[5]);
-	MONT_MAC(v0, v1, v2, u[19], m[4]);
-	MONT_MAC(w0, w1, w2, u[20], m[3]);
-	MONT_MAC(t0, t1, t2, u[21], m[2]);
-	MONT_MAC(v0, v1, v2, u[22], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[23] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[23], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MAC(t0, t1, t2, a[1], b[23]);
-	MONT_MUL(v0, v1, v2, a[2], b[22]);
-	MONT_MUL(w0, w1, w2, a[3], b[21]);
-	MONT_MAC(t0, t1, t2, a[4], b[20]);
-	MONT_MAC(v0, v1, v2, a[5], b[19]);
-	MONT_MAC(w0, w1, w2, a[6], b[18]);
-	MONT_MAC(t0, t1, t2, a[7], b[17]);
-	MONT_MAC(v0, v1, v2, a[8], b[16]);
-	MONT_MAC(w0, w1, w2, a[9], b[15]);
-	MONT_MAC(t0, t1, t2, a[10], b[14]);
-	MONT_MAC(v0, v1, v2, a[11], b[13]);
-	MONT_MAC(w0, w1, w2, a[12], b[12]);
-	MONT_MAC(t0, t1, t2, a[13], b[11]);
-	MONT_MAC(v0, v1, v2, a[14], b[10]);
-	MONT_MAC(w0, w1, w2, a[15], b[9]);
-	MONT_MAC(t0, t1, t2, a[16], b[8]);
-	MONT_MAC(v0, v1, v2, a[17], b[7]);
-	MONT_MAC(w0, w1, w2, a[18], b[6]);
-	MONT_MAC(t0, t1, t2, a[19], b[5]);
-	MONT_MAC(v0, v1, v2, a[20], b[4]);
-	MONT_MAC(w0, w1, w2, a[21], b[3]);
-	MONT_MAC(t0, t1, t2, a[22], b[2]);
-	MONT_MAC(v0, v1, v2, a[23], b[1]);
-	MONT_MAC(w0, w1, w2, u[1], m[23]);
-	MONT_MAC(t0, t1, t2, u[2], m[22]);
-	MONT_MAC(v0, v1, v2, u[3], m[21]);
-	MONT_MAC(w0, w1, w2, u[4], m[20]);
-	MONT_MAC(t0, t1, t2, u[5], m[19]);
-	MONT_MAC(v0, v1, v2, u[6], m[18]);
-	MONT_MAC(w0, w1, w2, u[7], m[17]);
-	MONT_MAC(t0, t1, t2, u[8], m[16]);
-	MONT_MAC(v0, v1, v2, u[9], m[15]);
-	MONT_MAC(w0, w1, w2, u[10], m[14]);
-	MONT_MAC(t0, t1, t2, u[11], m[13]);
-	MONT_MAC(v0, v1, v2, u[12], m[12]);
-	MONT_MAC(w0, w1, w2, u[13], m[11]);
-	MONT_MAC(t0, t1, t2, u[14], m[10]);
-	MONT_MAC(v0, v1, v2, u[15], m[9]);
-	MONT_MAC(w0, w1, w2, u[16], m[8]);
-	MONT_MAC(t0, t1, t2, u[17], m[7]);
-	MONT_MAC(v0, v1, v2, u[18], m[6]);
-	MONT_MAC(w0, w1, w2, u[19], m[5]);
-	MONT_MAC(t0, t1, t2, u[20], m[4]);
-	MONT_MAC(v0, v1, v2, u[21], m[3]);
-	MONT_MAC(w0, w1, w2, u[22], m[2]);
-	MONT_MAC(t0, t1, t2, u[23], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MAC(t0, t1, t2, a[2], b[23]);
-	MONT_MUL(v0, v1, v2, a[3], b[22]);
-	MONT_MUL(w0, w1, w2, a[4], b[21]);
-	MONT_MAC(t0, t1, t2, a[5], b[20]);
-	MONT_MAC(v0, v1, v2, a[6], b[19]);
-	MONT_MAC(w0, w1, w2, a[7], b[18]);
-	MONT_MAC(t0, t1, t2, a[8], b[17]);
-	MONT_MAC(v0, v1, v2, a[9], b[16]);
-	MONT_MAC(w0, w1, w2, a[10], b[15]);
-	MONT_MAC(t0, t1, t2, a[11], b[14]);
-	MONT_MAC(v0, v1, v2, a[12], b[13]);
-	MONT_MAC(w0, w1, w2, a[13], b[12]);
-	MONT_MAC(t0, t1, t2, a[14], b[11]);
-	MONT_MAC(v0, v1, v2, a[15], b[10]);
-	MONT_MAC(w0, w1, w2, a[16], b[9]);
-	MONT_MAC(t0, t1, t2, a[17], b[8]);
-	MONT_MAC(v0, v1, v2, a[18], b[7]);
-	MONT_MAC(w0, w1, w2, a[19], b[6]);
-	MONT_MAC(t0, t1, t2, a[20], b[5]);
-	MONT_MAC(v0, v1, v2, a[21], b[4]);
-	MONT_MAC(w0, w1, w2, a[22], b[3]);
-	MONT_MAC(t0, t1, t2, a[23], b[2]);
-	MONT_MAC(v0, v1, v2, u[2], m[23]);
-	MONT_MAC(w0, w1, w2, u[3], m[22]);
-	MONT_MAC(t0, t1, t2, u[4], m[21]);
-	MONT_MAC(v0, v1, v2, u[5], m[20]);
-	MONT_MAC(w0, w1, w2, u[6], m[19]);
-	MONT_MAC(t0, t1, t2, u[7], m[18]);
-	MONT_MAC(v0, v1, v2, u[8], m[17]);
-	MONT_MAC(w0, w1, w2, u[9], m[16]);
-	MONT_MAC(t0, t1, t2, u[10], m[15]);
-	MONT_MAC(v0, v1, v2, u[11], m[14]);
-	MONT_MAC(w0, w1, w2, u[12], m[13]);
-	MONT_MAC(t0, t1, t2, u[13], m[12]);
-	MONT_MAC(v0, v1, v2, u[14], m[11]);
-	MONT_MAC(w0, w1, w2, u[15], m[10]);
-	MONT_MAC(t0, t1, t2, u[16], m[9]);
-	MONT_MAC(v0, v1, v2, u[17], m[8]);
-	MONT_MAC(w0, w1, w2, u[18], m[7]);
-	MONT_MAC(t0, t1, t2, u[19], m[6]);
-	MONT_MAC(v0, v1, v2, u[20], m[5]);
-	MONT_MAC(w0, w1, w2, u[21], m[4]);
-	MONT_MAC(t0, t1, t2, u[22], m[3]);
-	MONT_MAC(v0, v1, v2, u[23], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MAC(t0, t1, t2, a[3], b[23]);
-	MONT_MUL(v0, v1, v2, a[4], b[22]);
-	MONT_MUL(w0, w1, w2, a[5], b[21]);
-	MONT_MAC(t0, t1, t2, a[6], b[20]);
-	MONT_MAC(v0, v1, v2, a[7], b[19]);
-	MONT_MAC(w0, w1, w2, a[8], b[18]);
-	MONT_MAC(t0, t1, t2, a[9], b[17]);
-	MONT_MAC(v0, v1, v2, a[10], b[16]);
-	MONT_MAC(w0, w1, w2, a[11], b[15]);
-	MONT_MAC(t0, t1, t2, a[12], b[14]);
-	MONT_MAC(v0, v1, v2, a[13], b[13]);
-	MONT_MAC(w0, w1, w2, a[14], b[12]);
-	MONT_MAC(t0, t1, t2, a[15], b[11]);
-	MONT_MAC(v0, v1, v2, a[16], b[10]);
-	MONT_MAC(w0, w1, w2, a[17], b[9]);
-	MONT_MAC(t0, t1, t2, a[18], b[8]);
-	MONT_MAC(v0, v1, v2, a[19], b[7]);
-	MONT_MAC(w0, w1, w2, a[20], b[6]);
-	MONT_MAC(t0, t1, t2, a[21], b[5]);
-	MONT_MAC(v0, v1, v2, a[22], b[4]);
-	MONT_MAC(w0, w1, w2, a[23], b[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[23]);
-	MONT_MAC(v0, v1, v2, u[4], m[22]);
-	MONT_MAC(w0, w1, w2, u[5], m[21]);
-	MONT_MAC(t0, t1, t2, u[6], m[20]);
-	MONT_MAC(v0, v1, v2, u[7], m[19]);
-	MONT_MAC(w0, w1, w2, u[8], m[18]);
-	MONT_MAC(t0, t1, t2, u[9], m[17]);
-	MONT_MAC(v0, v1, v2, u[10], m[16]);
-	MONT_MAC(w0, w1, w2, u[11], m[15]);
-	MONT_MAC(t0, t1, t2, u[12], m[14]);
-	MONT_MAC(v0, v1, v2, u[13], m[13]);
-	MONT_MAC(w0, w1, w2, u[14], m[12]);
-	MONT_MAC(t0, t1, t2, u[15], m[11]);
-	MONT_MAC(v0, v1, v2, u[16], m[10]);
-	MONT_MAC(w0, w1, w2, u[17], m[9]);
-	MONT_MAC(t0, t1, t2, u[18], m[8]);
-	MONT_MAC(v0, v1, v2, u[19], m[7]);
-	MONT_MAC(w0, w1, w2, u[20], m[6]);
-	MONT_MAC(t0, t1, t2, u[21], m[5]);
-	MONT_MAC(v0, v1, v2, u[22], m[4]);
-	MONT_MAC(w0, w1, w2, u[23], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MAC(t0, t1, t2, a[4], b[23]);
-	MONT_MUL(v0, v1, v2, a[5], b[22]);
-	MONT_MUL(w0, w1, w2, a[6], b[21]);
-	MONT_MAC(t0, t1, t2, a[7], b[20]);
-	MONT_MAC(v0, v1, v2, a[8], b[19]);
-	MONT_MAC(w0, w1, w2, a[9], b[18]);
-	MONT_MAC(t0, t1, t2, a[10], b[17]);
-	MONT_MAC(v0, v1, v2, a[11], b[16]);
-	MONT_MAC(w0, w1, w2, a[12], b[15]);
-	MONT_MAC(t0, t1, t2, a[13], b[14]);
-	MONT_MAC(v0, v1, v2, a[14], b[13]);
-	MONT_MAC(w0, w1, w2, a[15], b[12]);
-	MONT_MAC(t0, t1, t2, a[16], b[11]);
-	MONT_MAC(v0, v1, v2, a[17], b[10]);
-	MONT_MAC(w0, w1, w2, a[18], b[9]);
-	MONT_MAC(t0, t1, t2, a[19], b[8]);
-	MONT_MAC(v0, v1, v2, a[20], b[7]);
-	MONT_MAC(w0, w1, w2, a[21], b[6]);
-	MONT_MAC(t0, t1, t2, a[22], b[5]);
-	MONT_MAC(v0, v1, v2, a[23], b[4]);
-	MONT_MAC(w0, w1, w2, u[4], m[23]);
-	MONT_MAC(t0, t1, t2, u[5], m[22]);
-	MONT_MAC(v0, v1, v2, u[6], m[21]);
-	MONT_MAC(w0, w1, w2, u[7], m[20]);
-	MONT_MAC(t0, t1, t2, u[8], m[19]);
-	MONT_MAC(v0, v1, v2, u[9], m[18]);
-	MONT_MAC(w0, w1, w2, u[10], m[17]);
-	MONT_MAC(t0, t1, t2, u[11], m[16]);
-	MONT_MAC(v0, v1, v2, u[12], m[15]);
-	MONT_MAC(w0, w1, w2, u[13], m[14]);
-	MONT_MAC(t0, t1, t2, u[14], m[13]);
-	MONT_MAC(v0, v1, v2, u[15], m[12]);
-	MONT_MAC(w0, w1, w2, u[16], m[11]);
-	MONT_MAC(t0, t1, t2, u[17], m[10]);
-	MONT_MAC(v0, v1, v2, u[18], m[9]);
-	MONT_MAC(w0, w1, w2, u[19], m[8]);
-	MONT_MAC(t0, t1, t2, u[20], m[7]);
-	MONT_MAC(v0, v1, v2, u[21], m[6]);
-	MONT_MAC(w0, w1, w2, u[22], m[5]);
-	MONT_MAC(t0, t1, t2, u[23], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MAC(t0, t1, t2, a[5], b[23]);
-	MONT_MUL(v0, v1, v2, a[6], b[22]);
-	MONT_MUL(w0, w1, w2, a[7], b[21]);
-	MONT_MAC(t0, t1, t2, a[8], b[20]);
-	MONT_MAC(v0, v1, v2, a[9], b[19]);
-	MONT_MAC(w0, w1, w2, a[10], b[18]);
-	MONT_MAC(t0, t1, t2, a[11], b[17]);
-	MONT_MAC(v0, v1, v2, a[12], b[16]);
-	MONT_MAC(w0, w1, w2, a[13], b[15]);
-	MONT_MAC(t0, t1, t2, a[14], b[14]);
-	MONT_MAC(v0, v1, v2, a[15], b[13]);
-	MONT_MAC(w0, w1, w2, a[16], b[12]);
-	MONT_MAC(t0, t1, t2, a[17], b[11]);
-	MONT_MAC(v0, v1, v2, a[18], b[10]);
-	MONT_MAC(w0, w1, w2, a[19], b[9]);
-	MONT_MAC(t0, t1, t2, a[20], b[8]);
-	MONT_MAC(v0, v1, v2, a[21], b[7]);
-	MONT_MAC(w0, w1, w2, a[22], b[6]);
-	MONT_MAC(t0, t1, t2, a[23], b[5]);
-	MONT_MAC(v0, v1, v2, u[5], m[23]);
-	MONT_MAC(w0, w1, w2, u[6], m[22]);
-	MONT_MAC(t0, t1, t2, u[7], m[21]);
-	MONT_MAC(v0, v1, v2, u[8], m[20]);
-	MONT_MAC(w0, w1, w2, u[9], m[19]);
-	MONT_MAC(t0, t1, t2, u[10], m[18]);
-	MONT_MAC(v0, v1, v2, u[11], m[17]);
-	MONT_MAC(w0, w1, w2, u[12], m[16]);
-	MONT_MAC(t0, t1, t2, u[13], m[15]);
-	MONT_MAC(v0, v1, v2, u[14], m[14]);
-	MONT_MAC(w0, w1, w2, u[15], m[13]);
-	MONT_MAC(t0, t1, t2, u[16], m[12]);
-	MONT_MAC(v0, v1, v2, u[17], m[11]);
-	MONT_MAC(w0, w1, w2, u[18], m[10]);
-	MONT_MAC(t0, t1, t2, u[19], m[9]);
-	MONT_MAC(v0, v1, v2, u[20], m[8]);
-	MONT_MAC(w0, w1, w2, u[21], m[7]);
-	MONT_MAC(t0, t1, t2, u[22], m[6]);
-	MONT_MAC(v0, v1, v2, u[23], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MAC(t0, t1, t2, a[6], b[23]);
-	MONT_MUL(v0, v1, v2, a[7], b[22]);
-	MONT_MUL(w0, w1, w2, a[8], b[21]);
-	MONT_MAC(t0, t1, t2, a[9], b[20]);
-	MONT_MAC(v0, v1, v2, a[10], b[19]);
-	MONT_MAC(w0, w1, w2, a[11], b[18]);
-	MONT_MAC(t0, t1, t2, a[12], b[17]);
-	MONT_MAC(v0, v1, v2, a[13], b[16]);
-	MONT_MAC(w0, w1, w2, a[14], b[15]);
-	MONT_MAC(t0, t1, t2, a[15], b[14]);
-	MONT_MAC(v0, v1, v2, a[16], b[13]);
-	MONT_MAC(w0, w1, w2, a[17], b[12]);
-	MONT_MAC(t0, t1, t2, a[18], b[11]);
-	MONT_MAC(v0, v1, v2, a[19], b[10]);
-	MONT_MAC(w0, w1, w2, a[20], b[9]);
-	MONT_MAC(t0, t1, t2, a[21], b[8]);
-	MONT_MAC(v0, v1, v2, a[22], b[7]);
-	MONT_MAC(w0, w1, w2, a[23], b[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[23]);
-	MONT_MAC(v0, v1, v2, u[7], m[22]);
-	MONT_MAC(w0, w1, w2, u[8], m[21]);
-	MONT_MAC(t0, t1, t2, u[9], m[20]);
-	MONT_MAC(v0, v1, v2, u[10], m[19]);
-	MONT_MAC(w0, w1, w2, u[11], m[18]);
-	MONT_MAC(t0, t1, t2, u[12], m[17]);
-	MONT_MAC(v0, v1, v2, u[13], m[16]);
-	MONT_MAC(w0, w1, w2, u[14], m[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[14]);
-	MONT_MAC(v0, v1, v2, u[16], m[13]);
-	MONT_MAC(w0, w1, w2, u[17], m[12]);
-	MONT_MAC(t0, t1, t2, u[18], m[11]);
-	MONT_MAC(v0, v1, v2, u[19], m[10]);
-	MONT_MAC(w0, w1, w2, u[20], m[9]);
-	MONT_MAC(t0, t1, t2, u[21], m[8]);
-	MONT_MAC(v0, v1, v2, u[22], m[7]);
-	MONT_MAC(w0, w1, w2, u[23], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MAC(t0, t1, t2, a[7], b[23]);
-	MONT_MUL(v0, v1, v2, a[8], b[22]);
-	MONT_MUL(w0, w1, w2, a[9], b[21]);
-	MONT_MAC(t0, t1, t2, a[10], b[20]);
-	MONT_MAC(v0, v1, v2, a[11], b[19]);
-	MONT_MAC(w0, w1, w2, a[12], b[18]);
-	MONT_MAC(t0, t1, t2, a[13], b[17]);
-	MONT_MAC(v0, v1, v2, a[14], b[16]);
-	MONT_MAC(w0, w1, w2, a[15], b[15]);
-	MONT_MAC(t0, t1, t2, a[16], b[14]);
-	MONT_MAC(v0, v1, v2, a[17], b[13]);
-	MONT_MAC(w0, w1, w2, a[18], b[12]);
-	MONT_MAC(t0, t1, t2, a[19], b[11]);
-	MONT_MAC(v0, v1, v2, a[20], b[10]);
-	MONT_MAC(w0, w1, w2, a[21], b[9]);
-	MONT_MAC(t0, t1, t2, a[22], b[8]);
-	MONT_MAC(v0, v1, v2, a[23], b[7]);
-	MONT_MAC(w0, w1, w2, u[7], m[23]);
-	MONT_MAC(t0, t1, t2, u[8], m[22]);
-	MONT_MAC(v0, v1, v2, u[9], m[21]);
-	MONT_MAC(w0, w1, w2, u[10], m[20]);
-	MONT_MAC(t0, t1, t2, u[11], m[19]);
-	MONT_MAC(v0, v1, v2, u[12], m[18]);
-	MONT_MAC(w0, w1, w2, u[13], m[17]);
-	MONT_MAC(t0, t1, t2, u[14], m[16]);
-	MONT_MAC(v0, v1, v2, u[15], m[15]);
-	MONT_MAC(w0, w1, w2, u[16], m[14]);
-	MONT_MAC(t0, t1, t2, u[17], m[13]);
-	MONT_MAC(v0, v1, v2, u[18], m[12]);
-	MONT_MAC(w0, w1, w2, u[19], m[11]);
-	MONT_MAC(t0, t1, t2, u[20], m[10]);
-	MONT_MAC(v0, v1, v2, u[21], m[9]);
-	MONT_MAC(w0, w1, w2, u[22], m[8]);
-	MONT_MAC(t0, t1, t2, u[23], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 31 */
-	MONT_MAC(t0, t1, t2, a[8], b[23]);
-	MONT_MUL(v0, v1, v2, a[9], b[22]);
-	MONT_MUL(w0, w1, w2, a[10], b[21]);
-	MONT_MAC(t0, t1, t2, a[11], b[20]);
-	MONT_MAC(v0, v1, v2, a[12], b[19]);
-	MONT_MAC(w0, w1, w2, a[13], b[18]);
-	MONT_MAC(t0, t1, t2, a[14], b[17]);
-	MONT_MAC(v0, v1, v2, a[15], b[16]);
-	MONT_MAC(w0, w1, w2, a[16], b[15]);
-	MONT_MAC(t0, t1, t2, a[17], b[14]);
-	MONT_MAC(v0, v1, v2, a[18], b[13]);
-	MONT_MAC(w0, w1, w2, a[19], b[12]);
-	MONT_MAC(t0, t1, t2, a[20], b[11]);
-	MONT_MAC(v0, v1, v2, a[21], b[10]);
-	MONT_MAC(w0, w1, w2, a[22], b[9]);
-	MONT_MAC(t0, t1, t2, a[23], b[8]);
-	MONT_MAC(v0, v1, v2, u[8], m[23]);
-	MONT_MAC(w0, w1, w2, u[9], m[22]);
-	MONT_MAC(t0, t1, t2, u[10], m[21]);
-	MONT_MAC(v0, v1, v2, u[11], m[20]);
-	MONT_MAC(w0, w1, w2, u[12], m[19]);
-	MONT_MAC(t0, t1, t2, u[13], m[18]);
-	MONT_MAC(v0, v1, v2, u[14], m[17]);
-	MONT_MAC(w0, w1, w2, u[15], m[16]);
-	MONT_MAC(t0, t1, t2, u[16], m[15]);
-	MONT_MAC(v0, v1, v2, u[17], m[14]);
-	MONT_MAC(w0, w1, w2, u[18], m[13]);
-	MONT_MAC(t0, t1, t2, u[19], m[12]);
-	MONT_MAC(v0, v1, v2, u[20], m[11]);
-	MONT_MAC(w0, w1, w2, u[21], m[10]);
-	MONT_MAC(t0, t1, t2, u[22], m[9]);
-	MONT_MAC(v0, v1, v2, u[23], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 32 */
-	MONT_MAC(t0, t1, t2, a[9], b[23]);
-	MONT_MUL(v0, v1, v2, a[10], b[22]);
-	MONT_MUL(w0, w1, w2, a[11], b[21]);
-	MONT_MAC(t0, t1, t2, a[12], b[20]);
-	MONT_MAC(v0, v1, v2, a[13], b[19]);
-	MONT_MAC(w0, w1, w2, a[14], b[18]);
-	MONT_MAC(t0, t1, t2, a[15], b[17]);
-	MONT_MAC(v0, v1, v2, a[16], b[16]);
-	MONT_MAC(w0, w1, w2, a[17], b[15]);
-	MONT_MAC(t0, t1, t2, a[18], b[14]);
-	MONT_MAC(v0, v1, v2, a[19], b[13]);
-	MONT_MAC(w0, w1, w2, a[20], b[12]);
-	MONT_MAC(t0, t1, t2, a[21], b[11]);
-	MONT_MAC(v0, v1, v2, a[22], b[10]);
-	MONT_MAC(w0, w1, w2, a[23], b[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[23]);
-	MONT_MAC(v0, v1, v2, u[10], m[22]);
-	MONT_MAC(w0, w1, w2, u[11], m[21]);
-	MONT_MAC(t0, t1, t2, u[12], m[20]);
-	MONT_MAC(v0, v1, v2, u[13], m[19]);
-	MONT_MAC(w0, w1, w2, u[14], m[18]);
-	MONT_MAC(t0, t1, t2, u[15], m[17]);
-	MONT_MAC(v0, v1, v2, u[16], m[16]);
-	MONT_MAC(w0, w1, w2, u[17], m[15]);
-	MONT_MAC(t0, t1, t2, u[18], m[14]);
-	MONT_MAC(v0, v1, v2, u[19], m[13]);
-	MONT_MAC(w0, w1, w2, u[20], m[12]);
-	MONT_MAC(t0, t1, t2, u[21], m[11]);
-	MONT_MAC(v0, v1, v2, u[22], m[10]);
-	MONT_MAC(w0, w1, w2, u[23], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 33 */
-	MONT_MAC(t0, t1, t2, a[10], b[23]);
-	MONT_MUL(v0, v1, v2, a[11], b[22]);
-	MONT_MUL(w0, w1, w2, a[12], b[21]);
-	MONT_MAC(t0, t1, t2, a[13], b[20]);
-	MONT_MAC(v0, v1, v2, a[14], b[19]);
-	MONT_MAC(w0, w1, w2, a[15], b[18]);
-	MONT_MAC(t0, t1, t2, a[16], b[17]);
-	MONT_MAC(v0, v1, v2, a[17], b[16]);
-	MONT_MAC(w0, w1, w2, a[18], b[15]);
-	MONT_MAC(t0, t1, t2, a[19], b[14]);
-	MONT_MAC(v0, v1, v2, a[20], b[13]);
-	MONT_MAC(w0, w1, w2, a[21], b[12]);
-	MONT_MAC(t0, t1, t2, a[22], b[11]);
-	MONT_MAC(v0, v1, v2, a[23], b[10]);
-	MONT_MAC(w0, w1, w2, u[10], m[23]);
-	MONT_MAC(t0, t1, t2, u[11], m[22]);
-	MONT_MAC(v0, v1, v2, u[12], m[21]);
-	MONT_MAC(w0, w1, w2, u[13], m[20]);
-	MONT_MAC(t0, t1, t2, u[14], m[19]);
-	MONT_MAC(v0, v1, v2, u[15], m[18]);
-	MONT_MAC(w0, w1, w2, u[16], m[17]);
-	MONT_MAC(t0, t1, t2, u[17], m[16]);
-	MONT_MAC(v0, v1, v2, u[18], m[15]);
-	MONT_MAC(w0, w1, w2, u[19], m[14]);
-	MONT_MAC(t0, t1, t2, u[20], m[13]);
-	MONT_MAC(v0, v1, v2, u[21], m[12]);
-	MONT_MAC(w0, w1, w2, u[22], m[11]);
-	MONT_MAC(t0, t1, t2, u[23], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 34 */
-	MONT_MAC(t0, t1, t2, a[11], b[23]);
-	MONT_MUL(v0, v1, v2, a[12], b[22]);
-	MONT_MUL(w0, w1, w2, a[13], b[21]);
-	MONT_MAC(t0, t1, t2, a[14], b[20]);
-	MONT_MAC(v0, v1, v2, a[15], b[19]);
-	MONT_MAC(w0, w1, w2, a[16], b[18]);
-	MONT_MAC(t0, t1, t2, a[17], b[17]);
-	MONT_MAC(v0, v1, v2, a[18], b[16]);
-	MONT_MAC(w0, w1, w2, a[19], b[15]);
-	MONT_MAC(t0, t1, t2, a[20], b[14]);
-	MONT_MAC(v0, v1, v2, a[21], b[13]);
-	MONT_MAC(w0, w1, w2, a[22], b[12]);
-	MONT_MAC(t0, t1, t2, a[23], b[11]);
-	MONT_MAC(v0, v1, v2, u[11], m[23]);
-	MONT_MAC(w0, w1, w2, u[12], m[22]);
-	MONT_MAC(t0, t1, t2, u[13], m[21]);
-	MONT_MAC(v0, v1, v2, u[14], m[20]);
-	MONT_MAC(w0, w1, w2, u[15], m[19]);
-	MONT_MAC(t0, t1, t2, u[16], m[18]);
-	MONT_MAC(v0, v1, v2, u[17], m[17]);
-	MONT_MAC(w0, w1, w2, u[18], m[16]);
-	MONT_MAC(t0, t1, t2, u[19], m[15]);
-	MONT_MAC(v0, v1, v2, u[20], m[14]);
-	MONT_MAC(w0, w1, w2, u[21], m[13]);
-	MONT_MAC(t0, t1, t2, u[22], m[12]);
-	MONT_MAC(v0, v1, v2, u[23], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 35 */
-	MONT_MAC(t0, t1, t2, a[12], b[23]);
-	MONT_MUL(v0, v1, v2, a[13], b[22]);
-	MONT_MUL(w0, w1, w2, a[14], b[21]);
-	MONT_MAC(t0, t1, t2, a[15], b[20]);
-	MONT_MAC(v0, v1, v2, a[16], b[19]);
-	MONT_MAC(w0, w1, w2, a[17], b[18]);
-	MONT_MAC(t0, t1, t2, a[18], b[17]);
-	MONT_MAC(v0, v1, v2, a[19], b[16]);
-	MONT_MAC(w0, w1, w2, a[20], b[15]);
-	MONT_MAC(t0, t1, t2, a[21], b[14]);
-	MONT_MAC(v0, v1, v2, a[22], b[13]);
-	MONT_MAC(w0, w1, w2, a[23], b[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[23]);
-	MONT_MAC(v0, v1, v2, u[13], m[22]);
-	MONT_MAC(w0, w1, w2, u[14], m[21]);
-	MONT_MAC(t0, t1, t2, u[15], m[20]);
-	MONT_MAC(v0, v1, v2, u[16], m[19]);
-	MONT_MAC(w0, w1, w2, u[17], m[18]);
-	MONT_MAC(t0, t1, t2, u[18], m[17]);
-	MONT_MAC(v0, v1, v2, u[19], m[16]);
-	MONT_MAC(w0, w1, w2, u[20], m[15]);
-	MONT_MAC(t0, t1, t2, u[21], m[14]);
-	MONT_MAC(v0, v1, v2, u[22], m[13]);
-	MONT_MAC(w0, w1, w2, u[23], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 36 */
-	MONT_MAC(t0, t1, t2, a[13], b[23]);
-	MONT_MUL(v0, v1, v2, a[14], b[22]);
-	MONT_MUL(w0, w1, w2, a[15], b[21]);
-	MONT_MAC(t0, t1, t2, a[16], b[20]);
-	MONT_MAC(v0, v1, v2, a[17], b[19]);
-	MONT_MAC(w0, w1, w2, a[18], b[18]);
-	MONT_MAC(t0, t1, t2, a[19], b[17]);
-	MONT_MAC(v0, v1, v2, a[20], b[16]);
-	MONT_MAC(w0, w1, w2, a[21], b[15]);
-	MONT_MAC(t0, t1, t2, a[22], b[14]);
-	MONT_MAC(v0, v1, v2, a[23], b[13]);
-	MONT_MAC(w0, w1, w2, u[13], m[23]);
-	MONT_MAC(t0, t1, t2, u[14], m[22]);
-	MONT_MAC(v0, v1, v2, u[15], m[21]);
-	MONT_MAC(w0, w1, w2, u[16], m[20]);
-	MONT_MAC(t0, t1, t2, u[17], m[19]);
-	MONT_MAC(v0, v1, v2, u[18], m[18]);
-	MONT_MAC(w0, w1, w2, u[19], m[17]);
-	MONT_MAC(t0, t1, t2, u[20], m[16]);
-	MONT_MAC(v0, v1, v2, u[21], m[15]);
-	MONT_MAC(w0, w1, w2, u[22], m[14]);
-	MONT_MAC(t0, t1, t2, u[23], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 37 */
-	MONT_MAC(t0, t1, t2, a[14], b[23]);
-	MONT_MUL(v0, v1, v2, a[15], b[22]);
-	MONT_MUL(w0, w1, w2, a[16], b[21]);
-	MONT_MAC(t0, t1, t2, a[17], b[20]);
-	MONT_MAC(v0, v1, v2, a[18], b[19]);
-	MONT_MAC(w0, w1, w2, a[19], b[18]);
-	MONT_MAC(t0, t1, t2, a[20], b[17]);
-	MONT_MAC(v0, v1, v2, a[21], b[16]);
-	MONT_MAC(w0, w1, w2, a[22], b[15]);
-	MONT_MAC(t0, t1, t2, a[23], b[14]);
-	MONT_MAC(v0, v1, v2, u[14], m[23]);
-	MONT_MAC(w0, w1, w2, u[15], m[22]);
-	MONT_MAC(t0, t1, t2, u[16], m[21]);
-	MONT_MAC(v0, v1, v2, u[17], m[20]);
-	MONT_MAC(w0, w1, w2, u[18], m[19]);
-	MONT_MAC(t0, t1, t2, u[19], m[18]);
-	MONT_MAC(v0, v1, v2, u[20], m[17]);
-	MONT_MAC(w0, w1, w2, u[21], m[16]);
-	MONT_MAC(t0, t1, t2, u[22], m[15]);
-	MONT_MAC(v0, v1, v2, u[23], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 38 */
-	MONT_MAC(t0, t1, t2, a[15], b[23]);
-	MONT_MUL(v0, v1, v2, a[16], b[22]);
-	MONT_MUL(w0, w1, w2, a[17], b[21]);
-	MONT_MAC(t0, t1, t2, a[18], b[20]);
-	MONT_MAC(v0, v1, v2, a[19], b[19]);
-	MONT_MAC(w0, w1, w2, a[20], b[18]);
-	MONT_MAC(t0, t1, t2, a[21], b[17]);
-	MONT_MAC(v0, v1, v2, a[22], b[16]);
-	MONT_MAC(w0, w1, w2, a[23], b[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[23]);
-	MONT_MAC(v0, v1, v2, u[16], m[22]);
-	MONT_MAC(w0, w1, w2, u[17], m[21]);
-	MONT_MAC(t0, t1, t2, u[18], m[20]);
-	MONT_MAC(v0, v1, v2, u[19], m[19]);
-	MONT_MAC(w0, w1, w2, u[20], m[18]);
-	MONT_MAC(t0, t1, t2, u[21], m[17]);
-	MONT_MAC(v0, v1, v2, u[22], m[16]);
-	MONT_MAC(w0, w1, w2, u[23], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[14] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 39 */
-	MONT_MAC(t0, t1, t2, a[16], b[23]);
-	MONT_MUL(v0, v1, v2, a[17], b[22]);
-	MONT_MUL(w0, w1, w2, a[18], b[21]);
-	MONT_MAC(t0, t1, t2, a[19], b[20]);
-	MONT_MAC(v0, v1, v2, a[20], b[19]);
-	MONT_MAC(w0, w1, w2, a[21], b[18]);
-	MONT_MAC(t0, t1, t2, a[22], b[17]);
-	MONT_MAC(v0, v1, v2, a[23], b[16]);
-	MONT_MAC(w0, w1, w2, u[16], m[23]);
-	MONT_MAC(t0, t1, t2, u[17], m[22]);
-	MONT_MAC(v0, v1, v2, u[18], m[21]);
-	MONT_MAC(w0, w1, w2, u[19], m[20]);
-	MONT_MAC(t0, t1, t2, u[20], m[19]);
-	MONT_MAC(v0, v1, v2, u[21], m[18]);
-	MONT_MAC(w0, w1, w2, u[22], m[17]);
-	MONT_MAC(t0, t1, t2, u[23], m[16]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[15] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 40 */
-	MONT_MAC(t0, t1, t2, a[17], b[23]);
-	MONT_MUL(v0, v1, v2, a[18], b[22]);
-	MONT_MUL(w0, w1, w2, a[19], b[21]);
-	MONT_MAC(t0, t1, t2, a[20], b[20]);
-	MONT_MAC(v0, v1, v2, a[21], b[19]);
-	MONT_MAC(w0, w1, w2, a[22], b[18]);
-	MONT_MAC(t0, t1, t2, a[23], b[17]);
-	MONT_MAC(v0, v1, v2, u[17], m[23]);
-	MONT_MAC(w0, w1, w2, u[18], m[22]);
-	MONT_MAC(t0, t1, t2, u[19], m[21]);
-	MONT_MAC(v0, v1, v2, u[20], m[20]);
-	MONT_MAC(w0, w1, w2, u[21], m[19]);
-	MONT_MAC(t0, t1, t2, u[22], m[18]);
-	MONT_MAC(v0, v1, v2, u[23], m[17]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[16] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 41 */
-	MONT_MAC(t0, t1, t2, a[18], b[23]);
-	MONT_MUL(v0, v1, v2, a[19], b[22]);
-	MONT_MUL(w0, w1, w2, a[20], b[21]);
-	MONT_MAC(t0, t1, t2, a[21], b[20]);
-	MONT_MAC(v0, v1, v2, a[22], b[19]);
-	MONT_MAC(w0, w1, w2, a[23], b[18]);
-	MONT_MAC(t0, t1, t2, u[18], m[23]);
-	MONT_MAC(v0, v1, v2, u[19], m[22]);
-	MONT_MAC(w0, w1, w2, u[20], m[21]);
-	MONT_MAC(t0, t1, t2, u[21], m[20]);
-	MONT_MAC(v0, v1, v2, u[22], m[19]);
-	MONT_MAC(w0, w1, w2, u[23], m[18]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[17] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 42 */
-	MONT_MAC(t0, t1, t2, a[19], b[23]);
-	MONT_MUL(v0, v1, v2, a[20], b[22]);
-	MONT_MUL(w0, w1, w2, a[21], b[21]);
-	MONT_MAC(t0, t1, t2, a[22], b[20]);
-	MONT_MAC(v0, v1, v2, a[23], b[19]);
-	MONT_MAC(w0, w1, w2, u[19], m[23]);
-	MONT_MAC(t0, t1, t2, u[20], m[22]);
-	MONT_MAC(v0, v1, v2, u[21], m[21]);
-	MONT_MAC(w0, w1, w2, u[22], m[20]);
-	MONT_MAC(t0, t1, t2, u[23], m[19]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[18] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 43 */
-	MONT_MAC(t0, t1, t2, a[20], b[23]);
-	MONT_MUL(v0, v1, v2, a[21], b[22]);
-	MONT_MUL(w0, w1, w2, a[22], b[21]);
-	MONT_MAC(t0, t1, t2, a[23], b[20]);
-	MONT_MAC(v0, v1, v2, u[20], m[23]);
-	MONT_MAC(w0, w1, w2, u[21], m[22]);
-	MONT_MAC(t0, t1, t2, u[22], m[21]);
-	MONT_MAC(v0, v1, v2, u[23], m[20]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[19] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 44 */
-	MONT_MAC(t0, t1, t2, a[21], b[23]);
-	MONT_MUL(v0, v1, v2, a[22], b[22]);
-	MONT_MUL(w0, w1, w2, a[23], b[21]);
-	MONT_MAC(t0, t1, t2, u[21], m[23]);
-	MONT_MAC(v0, v1, v2, u[22], m[22]);
-	MONT_MAC(w0, w1, w2, u[23], m[21]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[20] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 45 */
-	MONT_MAC(t0, t1, t2, a[22], b[23]);
-	MONT_MUL(v0, v1, v2, a[23], b[22]);
-	MONT_MUL(w0, w1, w2, u[22], m[23]);
-	MONT_MAC(t0, t1, t2, u[23], m[22]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[21] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 46 */
-	MONT_MAC(t0, t1, t2, a[23], b[23]);
-	MONT_MUL(v0, v1, v2, u[23], m[23]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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_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, v0, v1, v2, w0, w1, w2, borrow, take;
-	limb_t s0, s1, s2, c0, c1, c2;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], a[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MUL(s0, s1, s2, a[0], a[1]);
-	MONT_MAC(t0, t1, t2, u[0], m[1]);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MUL(s0, s1, s2, a[0], a[2]);
-	MONT_MAC(t0, t1, t2, a[1], a[1]);
-	MONT_MUL(v0, v1, v2, u[0], m[2]);
-	MONT_MUL(w0, w1, w2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MUL(s0, s1, s2, a[0], a[3]);
-	MONT_MUL(c0, c1, c2, a[1], a[2]);
-	MONT_MAC(t0, t1, t2, u[0], m[3]);
-	MONT_MUL(v0, v1, v2, u[1], m[2]);
-	MONT_MUL(w0, w1, w2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MUL(s0, s1, s2, a[0], a[4]);
-	MONT_MUL(c0, c1, c2, a[1], a[3]);
-	MONT_MAC(t0, t1, t2, a[2], a[2]);
-	MONT_MUL(v0, v1, v2, u[0], m[4]);
-	MONT_MUL(w0, w1, w2, u[1], m[3]);
-	MONT_MAC(t0, t1, t2, u[2], m[2]);
-	MONT_MAC(v0, v1, v2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MUL(s0, s1, s2, a[0], a[5]);
-	MONT_MUL(c0, c1, c2, a[1], a[4]);
-	MONT_MAC(s0, s1, s2, a[2], a[3]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MUL(v0, v1, v2, u[1], m[4]);
-	MONT_MUL(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MUL(s0, s1, s2, a[0], a[6]);
-	MONT_MUL(c0, c1, c2, a[1], a[5]);
-	MONT_MAC(s0, s1, s2, a[2], a[4]);
-	MONT_MAC(t0, t1, t2, a[3], a[3]);
-	MONT_MUL(v0, v1, v2, u[0], m[6]);
-	MONT_MUL(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MUL(s0, s1, s2, a[0], a[7]);
-	MONT_MUL(c0, c1, c2, a[1], a[6]);
-	MONT_MAC(s0, s1, s2, a[2], a[5]);
-	MONT_MAC(c0, c1, c2, a[3], a[4]);
-	MONT_MAC(t0, t1, t2, u[0], m[7]);
-	MONT_MUL(v0, v1, v2, u[1], m[6]);
-	MONT_MUL(w0, w1, w2, u[2], m[5]);
-	MONT_MAC(t0, t1, t2, u[3], m[4]);
-	MONT_MAC(v0, v1, v2, u[4], m[3]);
-	MONT_MAC(w0, w1, w2, u[5], m[2]);
-	MONT_MAC(t0, t1, t2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MUL(s0, s1, s2, a[0], a[8]);
-	MONT_MUL(c0, c1, c2, a[1], a[7]);
-	MONT_MAC(s0, s1, s2, a[2], a[6]);
-	MONT_MAC(c0, c1, c2, a[3], a[5]);
-	MONT_MAC(t0, t1, t2, a[4], a[4]);
-	MONT_MUL(v0, v1, v2, u[0], m[8]);
-	MONT_MUL(w0, w1, w2, u[1], m[7]);
-	MONT_MAC(t0, t1, t2, u[2], m[6]);
-	MONT_MAC(v0, v1, v2, u[3], m[5]);
-	MONT_MAC(w0, w1, w2, u[4], m[4]);
-	MONT_MAC(t0, t1, t2, u[5], m[3]);
-	MONT_MAC(v0, v1, v2, u[6], m[2]);
-	MONT_MAC(w0, w1, w2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MUL(s0, s1, s2, a[0], a[9]);
-	MONT_MUL(c0, c1, c2, a[1], a[8]);
-	MONT_MAC(s0, s1, s2, a[2], a[7]);
-	MONT_MAC(c0, c1, c2, a[3], a[6]);
-	MONT_MAC(s0, s1, s2, a[4], a[5]);
-	MONT_MAC(t0, t1, t2, u[0], m[9]);
-	MONT_MUL(v0, v1, v2, u[1], m[8]);
-	MONT_MUL(w0, w1, w2, u[2], m[7]);
-	MONT_MAC(t0, t1, t2, u[3], m[6]);
-	MONT_MAC(v0, v1, v2, u[4], m[5]);
-	MONT_MAC(w0, w1, w2, u[5], m[4]);
-	MONT_MAC(t0, t1, t2, u[6], m[3]);
-	MONT_MAC(v0, v1, v2, u[7], m[2]);
-	MONT_MAC(w0, w1, w2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MUL(s0, s1, s2, a[0], a[10]);
-	MONT_MUL(c0, c1, c2, a[1], a[9]);
-	MONT_MAC(s0, s1, s2, a[2], a[8]);
-	MONT_MAC(c0, c1, c2, a[3], a[7]);
-	MONT_MAC(s0, s1, s2, a[4], a[6]);
-	MONT_MAC(t0, t1, t2, a[5], a[5]);
-	MONT_MUL(v0, v1, v2, u[0], m[10]);
-	MONT_MUL(w0, w1, w2, u[1], m[9]);
-	MONT_MAC(t0, t1, t2, u[2], m[8]);
-	MONT_MAC(v0, v1, v2, u[3], m[7]);
-	MONT_MAC(w0, w1, w2, u[4], m[6]);
-	MONT_MAC(t0, t1, t2, u[5], m[5]);
-	MONT_MAC(v0, v1, v2, u[6], m[4]);
-	MONT_MAC(w0, w1, w2, u[7], m[3]);
-	MONT_MAC(t0, t1, t2, u[8], m[2]);
-	MONT_MAC(v0, v1, v2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MUL(s0, s1, s2, a[0], a[11]);
-	MONT_MUL(c0, c1, c2, a[1], a[10]);
-	MONT_MAC(s0, s1, s2, a[2], a[9]);
-	MONT_MAC(c0, c1, c2, a[3], a[8]);
-	MONT_MAC(s0, s1, s2, a[4], a[7]);
-	MONT_MAC(c0, c1, c2, a[5], a[6]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MUL(v0, v1, v2, u[1], m[10]);
-	MONT_MUL(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MUL(s0, s1, s2, a[0], a[12]);
-	MONT_MUL(c0, c1, c2, a[1], a[11]);
-	MONT_MAC(s0, s1, s2, a[2], a[10]);
-	MONT_MAC(c0, c1, c2, a[3], a[9]);
-	MONT_MAC(s0, s1, s2, a[4], a[8]);
-	MONT_MAC(c0, c1, c2, a[5], a[7]);
-	MONT_MAC(t0, t1, t2, a[6], a[6]);
-	MONT_MUL(v0, v1, v2, u[0], m[12]);
-	MONT_MUL(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MUL(s0, s1, s2, a[0], a[13]);
-	MONT_MUL(c0, c1, c2, a[1], a[12]);
-	MONT_MAC(s0, s1, s2, a[2], a[11]);
-	MONT_MAC(c0, c1, c2, a[3], a[10]);
-	MONT_MAC(s0, s1, s2, a[4], a[9]);
-	MONT_MAC(c0, c1, c2, a[5], a[8]);
-	MONT_MAC(s0, s1, s2, a[6], a[7]);
-	MONT_MAC(t0, t1, t2, u[0], m[13]);
-	MONT_MUL(v0, v1, v2, u[1], m[12]);
-	MONT_MUL(w0, w1, w2, u[2], m[11]);
-	MONT_MAC(t0, t1, t2, u[3], m[10]);
-	MONT_MAC(v0, v1, v2, u[4], m[9]);
-	MONT_MAC(w0, w1, w2, u[5], m[8]);
-	MONT_MAC(t0, t1, t2, u[6], m[7]);
-	MONT_MAC(v0, v1, v2, u[7], m[6]);
-	MONT_MAC(w0, w1, w2, u[8], m[5]);
-	MONT_MAC(t0, t1, t2, u[9], m[4]);
-	MONT_MAC(v0, v1, v2, u[10], m[3]);
-	MONT_MAC(w0, w1, w2, u[11], m[2]);
-	MONT_MAC(t0, t1, t2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MUL(s0, s1, s2, a[0], a[14]);
-	MONT_MUL(c0, c1, c2, a[1], a[13]);
-	MONT_MAC(s0, s1, s2, a[2], a[12]);
-	MONT_MAC(c0, c1, c2, a[3], a[11]);
-	MONT_MAC(s0, s1, s2, a[4], a[10]);
-	MONT_MAC(c0, c1, c2, a[5], a[9]);
-	MONT_MAC(s0, s1, s2, a[6], a[8]);
-	MONT_MAC(t0, t1, t2, a[7], a[7]);
-	MONT_MUL(v0, v1, v2, u[0], m[14]);
-	MONT_MUL(w0, w1, w2, u[1], m[13]);
-	MONT_MAC(t0, t1, t2, u[2], m[12]);
-	MONT_MAC(v0, v1, v2, u[3], m[11]);
-	MONT_MAC(w0, w1, w2, u[4], m[10]);
-	MONT_MAC(t0, t1, t2, u[5], m[9]);
-	MONT_MAC(v0, v1, v2, u[6], m[8]);
-	MONT_MAC(w0, w1, w2, u[7], m[7]);
-	MONT_MAC(t0, t1, t2, u[8], m[6]);
-	MONT_MAC(v0, v1, v2, u[9], m[5]);
-	MONT_MAC(w0, w1, w2, u[10], m[4]);
-	MONT_MAC(t0, t1, t2, u[11], m[3]);
-	MONT_MAC(v0, v1, v2, u[12], m[2]);
-	MONT_MAC(w0, w1, w2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MUL(s0, s1, s2, a[0], a[15]);
-	MONT_MUL(c0, c1, c2, a[1], a[14]);
-	MONT_MAC(s0, s1, s2, a[2], a[13]);
-	MONT_MAC(c0, c1, c2, a[3], a[12]);
-	MONT_MAC(s0, s1, s2, a[4], a[11]);
-	MONT_MAC(c0, c1, c2, a[5], a[10]);
-	MONT_MAC(s0, s1, s2, a[6], a[9]);
-	MONT_MAC(c0, c1, c2, a[7], a[8]);
-	MONT_MAC(t0, t1, t2, u[0], m[15]);
-	MONT_MUL(v0, v1, v2, u[1], m[14]);
-	MONT_MUL(w0, w1, w2, u[2], m[13]);
-	MONT_MAC(t0, t1, t2, u[3], m[12]);
-	MONT_MAC(v0, v1, v2, u[4], m[11]);
-	MONT_MAC(w0, w1, w2, u[5], m[10]);
-	MONT_MAC(t0, t1, t2, u[6], m[9]);
-	MONT_MAC(v0, v1, v2, u[7], m[8]);
-	MONT_MAC(w0, w1, w2, u[8], m[7]);
-	MONT_MAC(t0, t1, t2, u[9], m[6]);
-	MONT_MAC(v0, v1, v2, u[10], m[5]);
-	MONT_MAC(w0, w1, w2, u[11], m[4]);
-	MONT_MAC(t0, t1, t2, u[12], m[3]);
-	MONT_MAC(v0, v1, v2, u[13], m[2]);
-	MONT_MAC(w0, w1, w2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MUL(s0, s1, s2, a[0], a[16]);
-	MONT_MUL(c0, c1, c2, a[1], a[15]);
-	MONT_MAC(s0, s1, s2, a[2], a[14]);
-	MONT_MAC(c0, c1, c2, a[3], a[13]);
-	MONT_MAC(s0, s1, s2, a[4], a[12]);
-	MONT_MAC(c0, c1, c2, a[5], a[11]);
-	MONT_MAC(s0, s1, s2, a[6], a[10]);
-	MONT_MAC(c0, c1, c2, a[7], a[9]);
-	MONT_MAC(t0, t1, t2, a[8], a[8]);
-	MONT_MUL(v0, v1, v2, u[0], m[16]);
-	MONT_MUL(w0, w1, w2, u[1], m[15]);
-	MONT_MAC(t0, t1, t2, u[2], m[14]);
-	MONT_MAC(v0, v1, v2, u[3], m[13]);
-	MONT_MAC(w0, w1, w2, u[4], m[12]);
-	MONT_MAC(t0, t1, t2, u[5], m[11]);
-	MONT_MAC(v0, v1, v2, u[6], m[10]);
-	MONT_MAC(w0, w1, w2, u[7], m[9]);
-	MONT_MAC(t0, t1, t2, u[8], m[8]);
-	MONT_MAC(v0, v1, v2, u[9], m[7]);
-	MONT_MAC(w0, w1, w2, u[10], m[6]);
-	MONT_MAC(t0, t1, t2, u[11], m[5]);
-	MONT_MAC(v0, v1, v2, u[12], m[4]);
-	MONT_MAC(w0, w1, w2, u[13], m[3]);
-	MONT_MAC(t0, t1, t2, u[14], m[2]);
-	MONT_MAC(v0, v1, v2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[16] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[16], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MUL(s0, s1, s2, a[0], a[17]);
-	MONT_MUL(c0, c1, c2, a[1], a[16]);
-	MONT_MAC(s0, s1, s2, a[2], a[15]);
-	MONT_MAC(c0, c1, c2, a[3], a[14]);
-	MONT_MAC(s0, s1, s2, a[4], a[13]);
-	MONT_MAC(c0, c1, c2, a[5], a[12]);
-	MONT_MAC(s0, s1, s2, a[6], a[11]);
-	MONT_MAC(c0, c1, c2, a[7], a[10]);
-	MONT_MAC(s0, s1, s2, a[8], a[9]);
-	MONT_MAC(t0, t1, t2, u[0], m[17]);
-	MONT_MUL(v0, v1, v2, u[1], m[16]);
-	MONT_MUL(w0, w1, w2, u[2], m[15]);
-	MONT_MAC(t0, t1, t2, u[3], m[14]);
-	MONT_MAC(v0, v1, v2, u[4], m[13]);
-	MONT_MAC(w0, w1, w2, u[5], m[12]);
-	MONT_MAC(t0, t1, t2, u[6], m[11]);
-	MONT_MAC(v0, v1, v2, u[7], m[10]);
-	MONT_MAC(w0, w1, w2, u[8], m[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[8]);
-	MONT_MAC(v0, v1, v2, u[10], m[7]);
-	MONT_MAC(w0, w1, w2, u[11], m[6]);
-	MONT_MAC(t0, t1, t2, u[12], m[5]);
-	MONT_MAC(v0, v1, v2, u[13], m[4]);
-	MONT_MAC(w0, w1, w2, u[14], m[3]);
-	MONT_MAC(t0, t1, t2, u[15], m[2]);
-	MONT_MAC(v0, v1, v2, u[16], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[17] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[17], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MUL(s0, s1, s2, a[0], a[18]);
-	MONT_MUL(c0, c1, c2, a[1], a[17]);
-	MONT_MAC(s0, s1, s2, a[2], a[16]);
-	MONT_MAC(c0, c1, c2, a[3], a[15]);
-	MONT_MAC(s0, s1, s2, a[4], a[14]);
-	MONT_MAC(c0, c1, c2, a[5], a[13]);
-	MONT_MAC(s0, s1, s2, a[6], a[12]);
-	MONT_MAC(c0, c1, c2, a[7], a[11]);
-	MONT_MAC(s0, s1, s2, a[8], a[10]);
-	MONT_MAC(t0, t1, t2, a[9], a[9]);
-	MONT_MUL(v0, v1, v2, u[0], m[18]);
-	MONT_MUL(w0, w1, w2, u[1], m[17]);
-	MONT_MAC(t0, t1, t2, u[2], m[16]);
-	MONT_MAC(v0, v1, v2, u[3], m[15]);
-	MONT_MAC(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_MAC(w0, w1, w2, u[16], m[2]);
-	MONT_MAC(t0, t1, t2, u[17], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[18] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[18], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MUL(s0, s1, s2, a[0], a[19]);
-	MONT_MUL(c0, c1, c2, a[1], a[18]);
-	MONT_MAC(s0, s1, s2, a[2], a[17]);
-	MONT_MAC(c0, c1, c2, a[3], a[16]);
-	MONT_MAC(s0, s1, s2, a[4], a[15]);
-	MONT_MAC(c0, c1, c2, a[5], a[14]);
-	MONT_MAC(s0, s1, s2, a[6], a[13]);
-	MONT_MAC(c0, c1, c2, a[7], a[12]);
-	MONT_MAC(s0, s1, s2, a[8], a[11]);
-	MONT_MAC(c0, c1, c2, a[9], a[10]);
-	MONT_MAC(t0, t1, t2, u[0], m[19]);
-	MONT_MUL(v0, v1, v2, u[1], m[18]);
-	MONT_MUL(w0, w1, w2, u[2], m[17]);
-	MONT_MAC(t0, t1, t2, u[3], m[16]);
-	MONT_MAC(v0, v1, v2, u[4], m[15]);
-	MONT_MAC(w0, w1, w2, u[5], m[14]);
-	MONT_MAC(t0, t1, t2, u[6], m[13]);
-	MONT_MAC(v0, v1, v2, u[7], m[12]);
-	MONT_MAC(w0, w1, w2, u[8], m[11]);
-	MONT_MAC(t0, t1, t2, u[9], m[10]);
-	MONT_MAC(v0, v1, v2, u[10], m[9]);
-	MONT_MAC(w0, w1, w2, u[11], m[8]);
-	MONT_MAC(t0, t1, t2, u[12], m[7]);
-	MONT_MAC(v0, v1, v2, u[13], m[6]);
-	MONT_MAC(w0, w1, w2, u[14], m[5]);
-	MONT_MAC(t0, t1, t2, u[15], m[4]);
-	MONT_MAC(v0, v1, v2, u[16], m[3]);
-	MONT_MAC(w0, w1, w2, u[17], m[2]);
-	MONT_MAC(t0, t1, t2, u[18], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[19] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[19], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MUL(s0, s1, s2, a[0], a[20]);
-	MONT_MUL(c0, c1, c2, a[1], a[19]);
-	MONT_MAC(s0, s1, s2, a[2], a[18]);
-	MONT_MAC(c0, c1, c2, a[3], a[17]);
-	MONT_MAC(s0, s1, s2, a[4], a[16]);
-	MONT_MAC(c0, c1, c2, a[5], a[15]);
-	MONT_MAC(s0, s1, s2, a[6], a[14]);
-	MONT_MAC(c0, c1, c2, a[7], a[13]);
-	MONT_MAC(s0, s1, s2, a[8], a[12]);
-	MONT_MAC(c0, c1, c2, a[9], a[11]);
-	MONT_MAC(t0, t1, t2, a[10], a[10]);
-	MONT_MUL(v0, v1, v2, u[0], m[20]);
-	MONT_MUL(w0, w1, w2, u[1], m[19]);
-	MONT_MAC(t0, t1, t2, u[2], m[18]);
-	MONT_MAC(v0, v1, v2, u[3], m[17]);
-	MONT_MAC(w0, w1, w2, u[4], m[16]);
-	MONT_MAC(t0, t1, t2, u[5], m[15]);
-	MONT_MAC(v0, v1, v2, u[6], m[14]);
-	MONT_MAC(w0, w1, w2, u[7], m[13]);
-	MONT_MAC(t0, t1, t2, u[8], m[12]);
-	MONT_MAC(v0, v1, v2, u[9], m[11]);
-	MONT_MAC(w0, w1, w2, u[10], m[10]);
-	MONT_MAC(t0, t1, t2, u[11], m[9]);
-	MONT_MAC(v0, v1, v2, u[12], m[8]);
-	MONT_MAC(w0, w1, w2, u[13], m[7]);
-	MONT_MAC(t0, t1, t2, u[14], m[6]);
-	MONT_MAC(v0, v1, v2, u[15], m[5]);
-	MONT_MAC(w0, w1, w2, u[16], m[4]);
-	MONT_MAC(t0, t1, t2, u[17], m[3]);
-	MONT_MAC(v0, v1, v2, u[18], m[2]);
-	MONT_MAC(w0, w1, w2, u[19], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[20] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[20], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MUL(s0, s1, s2, a[0], a[21]);
-	MONT_MUL(c0, c1, c2, a[1], a[20]);
-	MONT_MAC(s0, s1, s2, a[2], a[19]);
-	MONT_MAC(c0, c1, c2, a[3], a[18]);
-	MONT_MAC(s0, s1, s2, a[4], a[17]);
-	MONT_MAC(c0, c1, c2, a[5], a[16]);
-	MONT_MAC(s0, s1, s2, a[6], a[15]);
-	MONT_MAC(c0, c1, c2, a[7], a[14]);
-	MONT_MAC(s0, s1, s2, a[8], a[13]);
-	MONT_MAC(c0, c1, c2, a[9], a[12]);
-	MONT_MAC(s0, s1, s2, a[10], a[11]);
-	MONT_MAC(t0, t1, t2, u[0], m[21]);
-	MONT_MUL(v0, v1, v2, u[1], m[20]);
-	MONT_MUL(w0, w1, w2, u[2], m[19]);
-	MONT_MAC(t0, t1, t2, u[3], m[18]);
-	MONT_MAC(v0, v1, v2, u[4], m[17]);
-	MONT_MAC(w0, w1, w2, u[5], m[16]);
-	MONT_MAC(t0, t1, t2, u[6], m[15]);
-	MONT_MAC(v0, v1, v2, u[7], m[14]);
-	MONT_MAC(w0, w1, w2, u[8], m[13]);
-	MONT_MAC(t0, t1, t2, u[9], m[12]);
-	MONT_MAC(v0, v1, v2, u[10], m[11]);
-	MONT_MAC(w0, w1, w2, u[11], m[10]);
-	MONT_MAC(t0, t1, t2, u[12], m[9]);
-	MONT_MAC(v0, v1, v2, u[13], m[8]);
-	MONT_MAC(w0, w1, w2, u[14], m[7]);
-	MONT_MAC(t0, t1, t2, u[15], m[6]);
-	MONT_MAC(v0, v1, v2, u[16], m[5]);
-	MONT_MAC(w0, w1, w2, u[17], m[4]);
-	MONT_MAC(t0, t1, t2, u[18], m[3]);
-	MONT_MAC(v0, v1, v2, u[19], m[2]);
-	MONT_MAC(w0, w1, w2, u[20], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[21] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[21], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MUL(s0, s1, s2, a[0], a[22]);
-	MONT_MUL(c0, c1, c2, a[1], a[21]);
-	MONT_MAC(s0, s1, s2, a[2], a[20]);
-	MONT_MAC(c0, c1, c2, a[3], a[19]);
-	MONT_MAC(s0, s1, s2, a[4], a[18]);
-	MONT_MAC(c0, c1, c2, a[5], a[17]);
-	MONT_MAC(s0, s1, s2, a[6], a[16]);
-	MONT_MAC(c0, c1, c2, a[7], a[15]);
-	MONT_MAC(s0, s1, s2, a[8], a[14]);
-	MONT_MAC(c0, c1, c2, a[9], a[13]);
-	MONT_MAC(s0, s1, s2, a[10], a[12]);
-	MONT_MAC(t0, t1, t2, a[11], a[11]);
-	MONT_MUL(v0, v1, v2, u[0], m[22]);
-	MONT_MUL(w0, w1, w2, u[1], m[21]);
-	MONT_MAC(t0, t1, t2, u[2], m[20]);
-	MONT_MAC(v0, v1, v2, u[3], m[19]);
-	MONT_MAC(w0, w1, w2, u[4], m[18]);
-	MONT_MAC(t0, t1, t2, u[5], m[17]);
-	MONT_MAC(v0, v1, v2, u[6], m[16]);
-	MONT_MAC(w0, w1, w2, u[7], m[15]);
-	MONT_MAC(t0, t1, t2, u[8], m[14]);
-	MONT_MAC(v0, v1, v2, u[9], m[13]);
-	MONT_MAC(w0, w1, w2, u[10], m[12]);
-	MONT_MAC(t0, t1, t2, u[11], m[11]);
-	MONT_MAC(v0, v1, v2, u[12], m[10]);
-	MONT_MAC(w0, w1, w2, u[13], m[9]);
-	MONT_MAC(t0, t1, t2, u[14], m[8]);
-	MONT_MAC(v0, v1, v2, u[15], m[7]);
-	MONT_MAC(w0, w1, w2, u[16], m[6]);
-	MONT_MAC(t0, t1, t2, u[17], m[5]);
-	MONT_MAC(v0, v1, v2, u[18], m[4]);
-	MONT_MAC(w0, w1, w2, u[19], m[3]);
-	MONT_MAC(t0, t1, t2, u[20], m[2]);
-	MONT_MAC(v0, v1, v2, u[21], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[22] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[22], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MUL(s0, s1, s2, a[0], a[23]);
-	MONT_MUL(c0, c1, c2, a[1], a[22]);
-	MONT_MAC(s0, s1, s2, a[2], a[21]);
-	MONT_MAC(c0, c1, c2, a[3], a[20]);
-	MONT_MAC(s0, s1, s2, a[4], a[19]);
-	MONT_MAC(c0, c1, c2, a[5], a[18]);
-	MONT_MAC(s0, s1, s2, a[6], a[17]);
-	MONT_MAC(c0, c1, c2, a[7], a[16]);
-	MONT_MAC(s0, s1, s2, a[8], a[15]);
-	MONT_MAC(c0, c1, c2, a[9], a[14]);
-	MONT_MAC(s0, s1, s2, a[10], a[13]);
-	MONT_MAC(c0, c1, c2, a[11], a[12]);
-	MONT_MAC(t0, t1, t2, u[0], m[23]);
-	MONT_MUL(v0, v1, v2, u[1], m[22]);
-	MONT_MUL(w0, w1, w2, u[2], m[21]);
-	MONT_MAC(t0, t1, t2, u[3], m[20]);
-	MONT_MAC(v0, v1, v2, u[4], m[19]);
-	MONT_MAC(w0, w1, w2, u[5], m[18]);
-	MONT_MAC(t0, t1, t2, u[6], m[17]);
-	MONT_MAC(v0, v1, v2, u[7], m[16]);
-	MONT_MAC(w0, w1, w2, u[8], m[15]);
-	MONT_MAC(t0, t1, t2, u[9], m[14]);
-	MONT_MAC(v0, v1, v2, u[10], m[13]);
-	MONT_MAC(w0, w1, w2, u[11], m[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[11]);
-	MONT_MAC(v0, v1, v2, u[13], m[10]);
-	MONT_MAC(w0, w1, w2, u[14], m[9]);
-	MONT_MAC(t0, t1, t2, u[15], m[8]);
-	MONT_MAC(v0, v1, v2, u[16], m[7]);
-	MONT_MAC(w0, w1, w2, u[17], m[6]);
-	MONT_MAC(t0, t1, t2, u[18], m[5]);
-	MONT_MAC(v0, v1, v2, u[19], m[4]);
-	MONT_MAC(w0, w1, w2, u[20], m[3]);
-	MONT_MAC(t0, t1, t2, u[21], m[2]);
-	MONT_MAC(v0, v1, v2, u[22], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[23] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[23], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MUL(s0, s1, s2, a[1], a[23]);
-	MONT_MUL(c0, c1, c2, a[2], a[22]);
-	MONT_MAC(s0, s1, s2, a[3], a[21]);
-	MONT_MAC(c0, c1, c2, a[4], a[20]);
-	MONT_MAC(s0, s1, s2, a[5], a[19]);
-	MONT_MAC(c0, c1, c2, a[6], a[18]);
-	MONT_MAC(s0, s1, s2, a[7], a[17]);
-	MONT_MAC(c0, c1, c2, a[8], a[16]);
-	MONT_MAC(s0, s1, s2, a[9], a[15]);
-	MONT_MAC(c0, c1, c2, a[10], a[14]);
-	MONT_MAC(s0, s1, s2, a[11], a[13]);
-	MONT_MAC(t0, t1, t2, a[12], a[12]);
-	MONT_MUL(v0, v1, v2, u[1], m[23]);
-	MONT_MUL(w0, w1, w2, u[2], m[22]);
-	MONT_MAC(t0, t1, t2, u[3], m[21]);
-	MONT_MAC(v0, v1, v2, u[4], m[20]);
-	MONT_MAC(w0, w1, w2, u[5], m[19]);
-	MONT_MAC(t0, t1, t2, u[6], m[18]);
-	MONT_MAC(v0, v1, v2, u[7], m[17]);
-	MONT_MAC(w0, w1, w2, u[8], m[16]);
-	MONT_MAC(t0, t1, t2, u[9], m[15]);
-	MONT_MAC(v0, v1, v2, u[10], m[14]);
-	MONT_MAC(w0, w1, w2, u[11], m[13]);
-	MONT_MAC(t0, t1, t2, u[12], m[12]);
-	MONT_MAC(v0, v1, v2, u[13], m[11]);
-	MONT_MAC(w0, w1, w2, u[14], m[10]);
-	MONT_MAC(t0, t1, t2, u[15], m[9]);
-	MONT_MAC(v0, v1, v2, u[16], m[8]);
-	MONT_MAC(w0, w1, w2, u[17], m[7]);
-	MONT_MAC(t0, t1, t2, u[18], m[6]);
-	MONT_MAC(v0, v1, v2, u[19], m[5]);
-	MONT_MAC(w0, w1, w2, u[20], m[4]);
-	MONT_MAC(t0, t1, t2, u[21], m[3]);
-	MONT_MAC(v0, v1, v2, u[22], m[2]);
-	MONT_MAC(w0, w1, w2, u[23], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MUL(s0, s1, s2, a[2], a[23]);
-	MONT_MUL(c0, c1, c2, a[3], a[22]);
-	MONT_MAC(s0, s1, s2, a[4], a[21]);
-	MONT_MAC(c0, c1, c2, a[5], a[20]);
-	MONT_MAC(s0, s1, s2, a[6], a[19]);
-	MONT_MAC(c0, c1, c2, a[7], a[18]);
-	MONT_MAC(s0, s1, s2, a[8], a[17]);
-	MONT_MAC(c0, c1, c2, a[9], a[16]);
-	MONT_MAC(s0, s1, s2, a[10], a[15]);
-	MONT_MAC(c0, c1, c2, a[11], a[14]);
-	MONT_MAC(s0, s1, s2, a[12], a[13]);
-	MONT_MAC(t0, t1, t2, u[2], m[23]);
-	MONT_MUL(v0, v1, v2, u[3], m[22]);
-	MONT_MUL(w0, w1, w2, u[4], m[21]);
-	MONT_MAC(t0, t1, t2, u[5], m[20]);
-	MONT_MAC(v0, v1, v2, u[6], m[19]);
-	MONT_MAC(w0, w1, w2, u[7], m[18]);
-	MONT_MAC(t0, t1, t2, u[8], m[17]);
-	MONT_MAC(v0, v1, v2, u[9], m[16]);
-	MONT_MAC(w0, w1, w2, u[10], m[15]);
-	MONT_MAC(t0, t1, t2, u[11], m[14]);
-	MONT_MAC(v0, v1, v2, u[12], m[13]);
-	MONT_MAC(w0, w1, w2, u[13], m[12]);
-	MONT_MAC(t0, t1, t2, u[14], m[11]);
-	MONT_MAC(v0, v1, v2, u[15], m[10]);
-	MONT_MAC(w0, w1, w2, u[16], m[9]);
-	MONT_MAC(t0, t1, t2, u[17], m[8]);
-	MONT_MAC(v0, v1, v2, u[18], m[7]);
-	MONT_MAC(w0, w1, w2, u[19], m[6]);
-	MONT_MAC(t0, t1, t2, u[20], m[5]);
-	MONT_MAC(v0, v1, v2, u[21], m[4]);
-	MONT_MAC(w0, w1, w2, u[22], m[3]);
-	MONT_MAC(t0, t1, t2, u[23], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MUL(s0, s1, s2, a[3], a[23]);
-	MONT_MUL(c0, c1, c2, a[4], a[22]);
-	MONT_MAC(s0, s1, s2, a[5], a[21]);
-	MONT_MAC(c0, c1, c2, a[6], a[20]);
-	MONT_MAC(s0, s1, s2, a[7], a[19]);
-	MONT_MAC(c0, c1, c2, a[8], a[18]);
-	MONT_MAC(s0, s1, s2, a[9], a[17]);
-	MONT_MAC(c0, c1, c2, a[10], a[16]);
-	MONT_MAC(s0, s1, s2, a[11], a[15]);
-	MONT_MAC(c0, c1, c2, a[12], a[14]);
-	MONT_MAC(t0, t1, t2, a[13], a[13]);
-	MONT_MUL(v0, v1, v2, u[3], m[23]);
-	MONT_MUL(w0, w1, w2, u[4], m[22]);
-	MONT_MAC(t0, t1, t2, u[5], m[21]);
-	MONT_MAC(v0, v1, v2, u[6], m[20]);
-	MONT_MAC(w0, w1, w2, u[7], m[19]);
-	MONT_MAC(t0, t1, t2, u[8], m[18]);
-	MONT_MAC(v0, v1, v2, u[9], m[17]);
-	MONT_MAC(w0, w1, w2, u[10], m[16]);
-	MONT_MAC(t0, t1, t2, u[11], m[15]);
-	MONT_MAC(v0, v1, v2, u[12], m[14]);
-	MONT_MAC(w0, w1, w2, u[13], m[13]);
-	MONT_MAC(t0, t1, t2, u[14], m[12]);
-	MONT_MAC(v0, v1, v2, u[15], m[11]);
-	MONT_MAC(w0, w1, w2, u[16], m[10]);
-	MONT_MAC(t0, t1, t2, u[17], m[9]);
-	MONT_MAC(v0, v1, v2, u[18], m[8]);
-	MONT_MAC(w0, w1, w2, u[19], m[7]);
-	MONT_MAC(t0, t1, t2, u[20], m[6]);
-	MONT_MAC(v0, v1, v2, u[21], m[5]);
-	MONT_MAC(w0, w1, w2, u[22], m[4]);
-	MONT_MAC(t0, t1, t2, u[23], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MUL(s0, s1, s2, a[4], a[23]);
-	MONT_MUL(c0, c1, c2, a[5], a[22]);
-	MONT_MAC(s0, s1, s2, a[6], a[21]);
-	MONT_MAC(c0, c1, c2, a[7], a[20]);
-	MONT_MAC(s0, s1, s2, a[8], a[19]);
-	MONT_MAC(c0, c1, c2, a[9], a[18]);
-	MONT_MAC(s0, s1, s2, a[10], a[17]);
-	MONT_MAC(c0, c1, c2, a[11], a[16]);
-	MONT_MAC(s0, s1, s2, a[12], a[15]);
-	MONT_MAC(c0, c1, c2, a[13], a[14]);
-	MONT_MAC(t0, t1, t2, u[4], m[23]);
-	MONT_MUL(v0, v1, v2, u[5], m[22]);
-	MONT_MUL(w0, w1, w2, u[6], m[21]);
-	MONT_MAC(t0, t1, t2, u[7], m[20]);
-	MONT_MAC(v0, v1, v2, u[8], m[19]);
-	MONT_MAC(w0, w1, w2, u[9], m[18]);
-	MONT_MAC(t0, t1, t2, u[10], m[17]);
-	MONT_MAC(v0, v1, v2, u[11], m[16]);
-	MONT_MAC(w0, w1, w2, u[12], m[15]);
-	MONT_MAC(t0, t1, t2, u[13], m[14]);
-	MONT_MAC(v0, v1, v2, u[14], m[13]);
-	MONT_MAC(w0, w1, w2, u[15], m[12]);
-	MONT_MAC(t0, t1, t2, u[16], m[11]);
-	MONT_MAC(v0, v1, v2, u[17], m[10]);
-	MONT_MAC(w0, w1, w2, u[18], m[9]);
-	MONT_MAC(t0, t1, t2, u[19], m[8]);
-	MONT_MAC(v0, v1, v2, u[20], m[7]);
-	MONT_MAC(w0, w1, w2, u[21], m[6]);
-	MONT_MAC(t0, t1, t2, u[22], m[5]);
-	MONT_MAC(v0, v1, v2, u[23], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MUL(s0, s1, s2, a[5], a[23]);
-	MONT_MUL(c0, c1, c2, a[6], a[22]);
-	MONT_MAC(s0, s1, s2, a[7], a[21]);
-	MONT_MAC(c0, c1, c2, a[8], a[20]);
-	MONT_MAC(s0, s1, s2, a[9], a[19]);
-	MONT_MAC(c0, c1, c2, a[10], a[18]);
-	MONT_MAC(s0, s1, s2, a[11], a[17]);
-	MONT_MAC(c0, c1, c2, a[12], a[16]);
-	MONT_MAC(s0, s1, s2, a[13], a[15]);
-	MONT_MAC(t0, t1, t2, a[14], a[14]);
-	MONT_MUL(v0, v1, v2, u[5], m[23]);
-	MONT_MUL(w0, w1, w2, u[6], m[22]);
-	MONT_MAC(t0, t1, t2, u[7], m[21]);
-	MONT_MAC(v0, v1, v2, u[8], m[20]);
-	MONT_MAC(w0, w1, w2, u[9], m[19]);
-	MONT_MAC(t0, t1, t2, u[10], m[18]);
-	MONT_MAC(v0, v1, v2, u[11], m[17]);
-	MONT_MAC(w0, w1, w2, u[12], m[16]);
-	MONT_MAC(t0, t1, t2, u[13], m[15]);
-	MONT_MAC(v0, v1, v2, u[14], m[14]);
-	MONT_MAC(w0, w1, w2, u[15], m[13]);
-	MONT_MAC(t0, t1, t2, u[16], m[12]);
-	MONT_MAC(v0, v1, v2, u[17], m[11]);
-	MONT_MAC(w0, w1, w2, u[18], m[10]);
-	MONT_MAC(t0, t1, t2, u[19], m[9]);
-	MONT_MAC(v0, v1, v2, u[20], m[8]);
-	MONT_MAC(w0, w1, w2, u[21], m[7]);
-	MONT_MAC(t0, t1, t2, u[22], m[6]);
-	MONT_MAC(v0, v1, v2, u[23], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MUL(s0, s1, s2, a[6], a[23]);
-	MONT_MUL(c0, c1, c2, a[7], a[22]);
-	MONT_MAC(s0, s1, s2, a[8], a[21]);
-	MONT_MAC(c0, c1, c2, a[9], a[20]);
-	MONT_MAC(s0, s1, s2, a[10], a[19]);
-	MONT_MAC(c0, c1, c2, a[11], a[18]);
-	MONT_MAC(s0, s1, s2, a[12], a[17]);
-	MONT_MAC(c0, c1, c2, a[13], a[16]);
-	MONT_MAC(s0, s1, s2, a[14], a[15]);
-	MONT_MAC(t0, t1, t2, u[6], m[23]);
-	MONT_MUL(v0, v1, v2, u[7], m[22]);
-	MONT_MUL(w0, w1, w2, u[8], m[21]);
-	MONT_MAC(t0, t1, t2, u[9], m[20]);
-	MONT_MAC(v0, v1, v2, u[10], m[19]);
-	MONT_MAC(w0, w1, w2, u[11], m[18]);
-	MONT_MAC(t0, t1, t2, u[12], m[17]);
-	MONT_MAC(v0, v1, v2, u[13], m[16]);
-	MONT_MAC(w0, w1, w2, u[14], m[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[14]);
-	MONT_MAC(v0, v1, v2, u[16], m[13]);
-	MONT_MAC(w0, w1, w2, u[17], m[12]);
-	MONT_MAC(t0, t1, t2, u[18], m[11]);
-	MONT_MAC(v0, v1, v2, u[19], m[10]);
-	MONT_MAC(w0, w1, w2, u[20], m[9]);
-	MONT_MAC(t0, t1, t2, u[21], m[8]);
-	MONT_MAC(v0, v1, v2, u[22], m[7]);
-	MONT_MAC(w0, w1, w2, u[23], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MUL(s0, s1, s2, a[7], a[23]);
-	MONT_MUL(c0, c1, c2, a[8], a[22]);
-	MONT_MAC(s0, s1, s2, a[9], a[21]);
-	MONT_MAC(c0, c1, c2, a[10], a[20]);
-	MONT_MAC(s0, s1, s2, a[11], a[19]);
-	MONT_MAC(c0, c1, c2, a[12], a[18]);
-	MONT_MAC(s0, s1, s2, a[13], a[17]);
-	MONT_MAC(c0, c1, c2, a[14], a[16]);
-	MONT_MAC(t0, t1, t2, a[15], a[15]);
-	MONT_MUL(v0, v1, v2, u[7], m[23]);
-	MONT_MUL(w0, w1, w2, u[8], m[22]);
-	MONT_MAC(t0, t1, t2, u[9], m[21]);
-	MONT_MAC(v0, v1, v2, u[10], m[20]);
-	MONT_MAC(w0, w1, w2, u[11], m[19]);
-	MONT_MAC(t0, t1, t2, u[12], m[18]);
-	MONT_MAC(v0, v1, v2, u[13], m[17]);
-	MONT_MAC(w0, w1, w2, u[14], m[16]);
-	MONT_MAC(t0, t1, t2, u[15], m[15]);
-	MONT_MAC(v0, v1, v2, u[16], m[14]);
-	MONT_MAC(w0, w1, w2, u[17], m[13]);
-	MONT_MAC(t0, t1, t2, u[18], m[12]);
-	MONT_MAC(v0, v1, v2, u[19], m[11]);
-	MONT_MAC(w0, w1, w2, u[20], m[10]);
-	MONT_MAC(t0, t1, t2, u[21], m[9]);
-	MONT_MAC(v0, v1, v2, u[22], m[8]);
-	MONT_MAC(w0, w1, w2, u[23], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 31 */
-	MONT_MUL(s0, s1, s2, a[8], a[23]);
-	MONT_MUL(c0, c1, c2, a[9], a[22]);
-	MONT_MAC(s0, s1, s2, a[10], a[21]);
-	MONT_MAC(c0, c1, c2, a[11], a[20]);
-	MONT_MAC(s0, s1, s2, a[12], a[19]);
-	MONT_MAC(c0, c1, c2, a[13], a[18]);
-	MONT_MAC(s0, s1, s2, a[14], a[17]);
-	MONT_MAC(c0, c1, c2, a[15], a[16]);
-	MONT_MAC(t0, t1, t2, u[8], m[23]);
-	MONT_MUL(v0, v1, v2, u[9], m[22]);
-	MONT_MUL(w0, w1, w2, u[10], m[21]);
-	MONT_MAC(t0, t1, t2, u[11], m[20]);
-	MONT_MAC(v0, v1, v2, u[12], m[19]);
-	MONT_MAC(w0, w1, w2, u[13], m[18]);
-	MONT_MAC(t0, t1, t2, u[14], m[17]);
-	MONT_MAC(v0, v1, v2, u[15], m[16]);
-	MONT_MAC(w0, w1, w2, u[16], m[15]);
-	MONT_MAC(t0, t1, t2, u[17], m[14]);
-	MONT_MAC(v0, v1, v2, u[18], m[13]);
-	MONT_MAC(w0, w1, w2, u[19], m[12]);
-	MONT_MAC(t0, t1, t2, u[20], m[11]);
-	MONT_MAC(v0, v1, v2, u[21], m[10]);
-	MONT_MAC(w0, w1, w2, u[22], m[9]);
-	MONT_MAC(t0, t1, t2, u[23], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 32 */
-	MONT_MUL(s0, s1, s2, a[9], a[23]);
-	MONT_MUL(c0, c1, c2, a[10], a[22]);
-	MONT_MAC(s0, s1, s2, a[11], a[21]);
-	MONT_MAC(c0, c1, c2, a[12], a[20]);
-	MONT_MAC(s0, s1, s2, a[13], a[19]);
-	MONT_MAC(c0, c1, c2, a[14], a[18]);
-	MONT_MAC(s0, s1, s2, a[15], a[17]);
-	MONT_MAC(t0, t1, t2, a[16], a[16]);
-	MONT_MUL(v0, v1, v2, u[9], m[23]);
-	MONT_MUL(w0, w1, w2, u[10], m[22]);
-	MONT_MAC(t0, t1, t2, u[11], m[21]);
-	MONT_MAC(v0, v1, v2, u[12], m[20]);
-	MONT_MAC(w0, w1, w2, u[13], m[19]);
-	MONT_MAC(t0, t1, t2, u[14], m[18]);
-	MONT_MAC(v0, v1, v2, u[15], m[17]);
-	MONT_MAC(w0, w1, w2, u[16], m[16]);
-	MONT_MAC(t0, t1, t2, u[17], m[15]);
-	MONT_MAC(v0, v1, v2, u[18], m[14]);
-	MONT_MAC(w0, w1, w2, u[19], m[13]);
-	MONT_MAC(t0, t1, t2, u[20], m[12]);
-	MONT_MAC(v0, v1, v2, u[21], m[11]);
-	MONT_MAC(w0, w1, w2, u[22], m[10]);
-	MONT_MAC(t0, t1, t2, u[23], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 33 */
-	MONT_MUL(s0, s1, s2, a[10], a[23]);
-	MONT_MUL(c0, c1, c2, a[11], a[22]);
-	MONT_MAC(s0, s1, s2, a[12], a[21]);
-	MONT_MAC(c0, c1, c2, a[13], a[20]);
-	MONT_MAC(s0, s1, s2, a[14], a[19]);
-	MONT_MAC(c0, c1, c2, a[15], a[18]);
-	MONT_MAC(s0, s1, s2, a[16], a[17]);
-	MONT_MAC(t0, t1, t2, u[10], m[23]);
-	MONT_MUL(v0, v1, v2, u[11], m[22]);
-	MONT_MUL(w0, w1, w2, u[12], m[21]);
-	MONT_MAC(t0, t1, t2, u[13], m[20]);
-	MONT_MAC(v0, v1, v2, u[14], m[19]);
-	MONT_MAC(w0, w1, w2, u[15], m[18]);
-	MONT_MAC(t0, t1, t2, u[16], m[17]);
-	MONT_MAC(v0, v1, v2, u[17], m[16]);
-	MONT_MAC(w0, w1, w2, u[18], m[15]);
-	MONT_MAC(t0, t1, t2, u[19], m[14]);
-	MONT_MAC(v0, v1, v2, u[20], m[13]);
-	MONT_MAC(w0, w1, w2, u[21], m[12]);
-	MONT_MAC(t0, t1, t2, u[22], m[11]);
-	MONT_MAC(v0, v1, v2, u[23], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 34 */
-	MONT_MUL(s0, s1, s2, a[11], a[23]);
-	MONT_MUL(c0, c1, c2, a[12], a[22]);
-	MONT_MAC(s0, s1, s2, a[13], a[21]);
-	MONT_MAC(c0, c1, c2, a[14], a[20]);
-	MONT_MAC(s0, s1, s2, a[15], a[19]);
-	MONT_MAC(c0, c1, c2, a[16], a[18]);
-	MONT_MAC(t0, t1, t2, a[17], a[17]);
-	MONT_MUL(v0, v1, v2, u[11], m[23]);
-	MONT_MUL(w0, w1, w2, u[12], m[22]);
-	MONT_MAC(t0, t1, t2, u[13], m[21]);
-	MONT_MAC(v0, v1, v2, u[14], m[20]);
-	MONT_MAC(w0, w1, w2, u[15], m[19]);
-	MONT_MAC(t0, t1, t2, u[16], m[18]);
-	MONT_MAC(v0, v1, v2, u[17], m[17]);
-	MONT_MAC(w0, w1, w2, u[18], m[16]);
-	MONT_MAC(t0, t1, t2, u[19], m[15]);
-	MONT_MAC(v0, v1, v2, u[20], m[14]);
-	MONT_MAC(w0, w1, w2, u[21], m[13]);
-	MONT_MAC(t0, t1, t2, u[22], m[12]);
-	MONT_MAC(v0, v1, v2, u[23], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 35 */
-	MONT_MUL(s0, s1, s2, a[12], a[23]);
-	MONT_MUL(c0, c1, c2, a[13], a[22]);
-	MONT_MAC(s0, s1, s2, a[14], a[21]);
-	MONT_MAC(c0, c1, c2, a[15], a[20]);
-	MONT_MAC(s0, s1, s2, a[16], a[19]);
-	MONT_MAC(c0, c1, c2, a[17], a[18]);
-	MONT_MAC(t0, t1, t2, u[12], m[23]);
-	MONT_MUL(v0, v1, v2, u[13], m[22]);
-	MONT_MUL(w0, w1, w2, u[14], m[21]);
-	MONT_MAC(t0, t1, t2, u[15], m[20]);
-	MONT_MAC(v0, v1, v2, u[16], m[19]);
-	MONT_MAC(w0, w1, w2, u[17], m[18]);
-	MONT_MAC(t0, t1, t2, u[18], m[17]);
-	MONT_MAC(v0, v1, v2, u[19], m[16]);
-	MONT_MAC(w0, w1, w2, u[20], m[15]);
-	MONT_MAC(t0, t1, t2, u[21], m[14]);
-	MONT_MAC(v0, v1, v2, u[22], m[13]);
-	MONT_MAC(w0, w1, w2, u[23], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 36 */
-	MONT_MUL(s0, s1, s2, a[13], a[23]);
-	MONT_MUL(c0, c1, c2, a[14], a[22]);
-	MONT_MAC(s0, s1, s2, a[15], a[21]);
-	MONT_MAC(c0, c1, c2, a[16], a[20]);
-	MONT_MAC(s0, s1, s2, a[17], a[19]);
-	MONT_MAC(t0, t1, t2, a[18], a[18]);
-	MONT_MUL(v0, v1, v2, u[13], m[23]);
-	MONT_MUL(w0, w1, w2, u[14], m[22]);
-	MONT_MAC(t0, t1, t2, u[15], m[21]);
-	MONT_MAC(v0, v1, v2, u[16], m[20]);
-	MONT_MAC(w0, w1, w2, u[17], m[19]);
-	MONT_MAC(t0, t1, t2, u[18], m[18]);
-	MONT_MAC(v0, v1, v2, u[19], m[17]);
-	MONT_MAC(w0, w1, w2, u[20], m[16]);
-	MONT_MAC(t0, t1, t2, u[21], m[15]);
-	MONT_MAC(v0, v1, v2, u[22], m[14]);
-	MONT_MAC(w0, w1, w2, u[23], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 37 */
-	MONT_MUL(s0, s1, s2, a[14], a[23]);
-	MONT_MUL(c0, c1, c2, a[15], a[22]);
-	MONT_MAC(s0, s1, s2, a[16], a[21]);
-	MONT_MAC(c0, c1, c2, a[17], a[20]);
-	MONT_MAC(s0, s1, s2, a[18], a[19]);
-	MONT_MAC(t0, t1, t2, u[14], m[23]);
-	MONT_MUL(v0, v1, v2, u[15], m[22]);
-	MONT_MUL(w0, w1, w2, u[16], m[21]);
-	MONT_MAC(t0, t1, t2, u[17], m[20]);
-	MONT_MAC(v0, v1, v2, u[18], m[19]);
-	MONT_MAC(w0, w1, w2, u[19], m[18]);
-	MONT_MAC(t0, t1, t2, u[20], m[17]);
-	MONT_MAC(v0, v1, v2, u[21], m[16]);
-	MONT_MAC(w0, w1, w2, u[22], m[15]);
-	MONT_MAC(t0, t1, t2, u[23], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 38 */
-	MONT_MUL(s0, s1, s2, a[15], a[23]);
-	MONT_MUL(c0, c1, c2, a[16], a[22]);
-	MONT_MAC(s0, s1, s2, a[17], a[21]);
-	MONT_MAC(c0, c1, c2, a[18], a[20]);
-	MONT_MAC(t0, t1, t2, a[19], a[19]);
-	MONT_MUL(v0, v1, v2, u[15], m[23]);
-	MONT_MUL(w0, w1, w2, u[16], m[22]);
-	MONT_MAC(t0, t1, t2, u[17], m[21]);
-	MONT_MAC(v0, v1, v2, u[18], m[20]);
-	MONT_MAC(w0, w1, w2, u[19], m[19]);
-	MONT_MAC(t0, t1, t2, u[20], m[18]);
-	MONT_MAC(v0, v1, v2, u[21], m[17]);
-	MONT_MAC(w0, w1, w2, u[22], m[16]);
-	MONT_MAC(t0, t1, t2, u[23], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[14] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 39 */
-	MONT_MUL(s0, s1, s2, a[16], a[23]);
-	MONT_MUL(c0, c1, c2, a[17], a[22]);
-	MONT_MAC(s0, s1, s2, a[18], a[21]);
-	MONT_MAC(c0, c1, c2, a[19], a[20]);
-	MONT_MAC(t0, t1, t2, u[16], m[23]);
-	MONT_MUL(v0, v1, v2, u[17], m[22]);
-	MONT_MUL(w0, w1, w2, u[18], m[21]);
-	MONT_MAC(t0, t1, t2, u[19], m[20]);
-	MONT_MAC(v0, v1, v2, u[20], m[19]);
-	MONT_MAC(w0, w1, w2, u[21], m[18]);
-	MONT_MAC(t0, t1, t2, u[22], m[17]);
-	MONT_MAC(v0, v1, v2, u[23], m[16]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[15] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 40 */
-	MONT_MUL(s0, s1, s2, a[17], a[23]);
-	MONT_MUL(c0, c1, c2, a[18], a[22]);
-	MONT_MAC(s0, s1, s2, a[19], a[21]);
-	MONT_MAC(t0, t1, t2, a[20], a[20]);
-	MONT_MUL(v0, v1, v2, u[17], m[23]);
-	MONT_MUL(w0, w1, w2, u[18], m[22]);
-	MONT_MAC(t0, t1, t2, u[19], m[21]);
-	MONT_MAC(v0, v1, v2, u[20], m[20]);
-	MONT_MAC(w0, w1, w2, u[21], m[19]);
-	MONT_MAC(t0, t1, t2, u[22], m[18]);
-	MONT_MAC(v0, v1, v2, u[23], m[17]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[16] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 41 */
-	MONT_MUL(s0, s1, s2, a[18], a[23]);
-	MONT_MUL(c0, c1, c2, a[19], a[22]);
-	MONT_MAC(s0, s1, s2, a[20], a[21]);
-	MONT_MAC(t0, t1, t2, u[18], m[23]);
-	MONT_MUL(v0, v1, v2, u[19], m[22]);
-	MONT_MUL(w0, w1, w2, u[20], m[21]);
-	MONT_MAC(t0, t1, t2, u[21], m[20]);
-	MONT_MAC(v0, v1, v2, u[22], m[19]);
-	MONT_MAC(w0, w1, w2, u[23], m[18]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[17] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 42 */
-	MONT_MUL(s0, s1, s2, a[19], a[23]);
-	MONT_MUL(c0, c1, c2, a[20], a[22]);
-	MONT_MAC(t0, t1, t2, a[21], a[21]);
-	MONT_MUL(v0, v1, v2, u[19], m[23]);
-	MONT_MUL(w0, w1, w2, u[20], m[22]);
-	MONT_MAC(t0, t1, t2, u[21], m[21]);
-	MONT_MAC(v0, v1, v2, u[22], m[20]);
-	MONT_MAC(w0, w1, w2, u[23], m[19]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[18] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 43 */
-	MONT_MUL(s0, s1, s2, a[20], a[23]);
-	MONT_MUL(c0, c1, c2, a[21], a[22]);
-	MONT_MAC(t0, t1, t2, u[20], m[23]);
-	MONT_MUL(v0, v1, v2, u[21], m[22]);
-	MONT_MUL(w0, w1, w2, u[22], m[21]);
-	MONT_MAC(t0, t1, t2, u[23], m[20]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[19] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 44 */
-	MONT_MUL(s0, s1, s2, a[21], a[23]);
-	MONT_MAC(t0, t1, t2, a[22], a[22]);
-	MONT_MUL(v0, v1, v2, u[21], m[23]);
-	MONT_MUL(w0, w1, w2, u[22], m[22]);
-	MONT_MAC(t0, t1, t2, u[23], m[21]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[20] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 45 */
-	MONT_MUL(s0, s1, s2, a[22], a[23]);
-	MONT_MAC(t0, t1, t2, u[22], m[23]);
-	MONT_MUL(v0, v1, v2, u[23], m[22]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[21] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 46 */
-	MONT_MAC(t0, t1, t2, a[23], a[23]);
-	MONT_MUL(v0, v1, v2, u[23], m[23]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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 * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
-static void crypton_mont_mul32(limb_t *r, const limb_t *a, const limb_t *b,
-                               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, v0, v1, v2, w0, w1, w2, borrow, take;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], b[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MAC(t0, t1, t2, a[0], b[1]);
-	MONT_MUL(v0, v1, v2, a[1], b[0]);
-	MONT_MUL(w0, w1, w2, u[0], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MAC(t0, t1, t2, a[0], b[2]);
-	MONT_MUL(v0, v1, v2, a[1], b[1]);
-	MONT_MUL(w0, w1, w2, a[2], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[2]);
-	MONT_MAC(v0, v1, v2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MAC(t0, t1, t2, a[0], b[3]);
-	MONT_MUL(v0, v1, v2, a[1], b[2]);
-	MONT_MUL(w0, w1, w2, a[2], b[1]);
-	MONT_MAC(t0, t1, t2, a[3], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[3]);
-	MONT_MAC(w0, w1, w2, u[1], m[2]);
-	MONT_MAC(t0, t1, t2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MAC(t0, t1, t2, a[0], b[4]);
-	MONT_MUL(v0, v1, v2, a[1], b[3]);
-	MONT_MUL(w0, w1, w2, a[2], b[2]);
-	MONT_MAC(t0, t1, t2, a[3], b[1]);
-	MONT_MAC(v0, v1, v2, a[4], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[4]);
-	MONT_MAC(t0, t1, t2, u[1], m[3]);
-	MONT_MAC(v0, v1, v2, u[2], m[2]);
-	MONT_MAC(w0, w1, w2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MAC(t0, t1, t2, a[0], b[5]);
-	MONT_MUL(v0, v1, v2, a[1], b[4]);
-	MONT_MUL(w0, w1, w2, a[2], b[3]);
-	MONT_MAC(t0, t1, t2, a[3], b[2]);
-	MONT_MAC(v0, v1, v2, a[4], b[1]);
-	MONT_MAC(w0, w1, w2, a[5], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MAC(v0, v1, v2, u[1], m[4]);
-	MONT_MAC(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MAC(t0, t1, t2, a[0], b[6]);
-	MONT_MUL(v0, v1, v2, a[1], b[5]);
-	MONT_MUL(w0, w1, w2, a[2], b[4]);
-	MONT_MAC(t0, t1, t2, a[3], b[3]);
-	MONT_MAC(v0, v1, v2, a[4], b[2]);
-	MONT_MAC(w0, w1, w2, a[5], b[1]);
-	MONT_MAC(t0, t1, t2, a[6], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[6]);
-	MONT_MAC(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MAC(t0, t1, t2, a[0], b[7]);
-	MONT_MUL(v0, v1, v2, a[1], b[6]);
-	MONT_MUL(w0, w1, w2, a[2], b[5]);
-	MONT_MAC(t0, t1, t2, a[3], b[4]);
-	MONT_MAC(v0, v1, v2, a[4], b[3]);
-	MONT_MAC(w0, w1, w2, a[5], b[2]);
-	MONT_MAC(t0, t1, t2, a[6], b[1]);
-	MONT_MAC(v0, v1, v2, a[7], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[7]);
-	MONT_MAC(t0, t1, t2, u[1], m[6]);
-	MONT_MAC(v0, v1, v2, u[2], m[5]);
-	MONT_MAC(w0, w1, w2, u[3], m[4]);
-	MONT_MAC(t0, t1, t2, u[4], m[3]);
-	MONT_MAC(v0, v1, v2, u[5], m[2]);
-	MONT_MAC(w0, w1, w2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MAC(t0, t1, t2, a[0], b[8]);
-	MONT_MUL(v0, v1, v2, a[1], b[7]);
-	MONT_MUL(w0, w1, w2, a[2], b[6]);
-	MONT_MAC(t0, t1, t2, a[3], b[5]);
-	MONT_MAC(v0, v1, v2, a[4], b[4]);
-	MONT_MAC(w0, w1, w2, a[5], b[3]);
-	MONT_MAC(t0, t1, t2, a[6], b[2]);
-	MONT_MAC(v0, v1, v2, a[7], b[1]);
-	MONT_MAC(w0, w1, w2, a[8], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[8]);
-	MONT_MAC(v0, v1, v2, u[1], m[7]);
-	MONT_MAC(w0, w1, w2, u[2], m[6]);
-	MONT_MAC(t0, t1, t2, u[3], m[5]);
-	MONT_MAC(v0, v1, v2, u[4], m[4]);
-	MONT_MAC(w0, w1, w2, u[5], m[3]);
-	MONT_MAC(t0, t1, t2, u[6], m[2]);
-	MONT_MAC(v0, v1, v2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MAC(t0, t1, t2, a[0], b[9]);
-	MONT_MUL(v0, v1, v2, a[1], b[8]);
-	MONT_MUL(w0, w1, w2, a[2], b[7]);
-	MONT_MAC(t0, t1, t2, a[3], b[6]);
-	MONT_MAC(v0, v1, v2, a[4], b[5]);
-	MONT_MAC(w0, w1, w2, a[5], b[4]);
-	MONT_MAC(t0, t1, t2, a[6], b[3]);
-	MONT_MAC(v0, v1, v2, a[7], b[2]);
-	MONT_MAC(w0, w1, w2, a[8], b[1]);
-	MONT_MAC(t0, t1, t2, a[9], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[9]);
-	MONT_MAC(w0, w1, w2, u[1], m[8]);
-	MONT_MAC(t0, t1, t2, u[2], m[7]);
-	MONT_MAC(v0, v1, v2, u[3], m[6]);
-	MONT_MAC(w0, w1, w2, u[4], m[5]);
-	MONT_MAC(t0, t1, t2, u[5], m[4]);
-	MONT_MAC(v0, v1, v2, u[6], m[3]);
-	MONT_MAC(w0, w1, w2, u[7], m[2]);
-	MONT_MAC(t0, t1, t2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MAC(t0, t1, t2, a[0], b[10]);
-	MONT_MUL(v0, v1, v2, a[1], b[9]);
-	MONT_MUL(w0, w1, w2, a[2], b[8]);
-	MONT_MAC(t0, t1, t2, a[3], b[7]);
-	MONT_MAC(v0, v1, v2, a[4], b[6]);
-	MONT_MAC(w0, w1, w2, a[5], b[5]);
-	MONT_MAC(t0, t1, t2, a[6], b[4]);
-	MONT_MAC(v0, v1, v2, a[7], b[3]);
-	MONT_MAC(w0, w1, w2, a[8], b[2]);
-	MONT_MAC(t0, t1, t2, a[9], b[1]);
-	MONT_MAC(v0, v1, v2, a[10], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[10]);
-	MONT_MAC(t0, t1, t2, u[1], m[9]);
-	MONT_MAC(v0, v1, v2, u[2], m[8]);
-	MONT_MAC(w0, w1, w2, u[3], m[7]);
-	MONT_MAC(t0, t1, t2, u[4], m[6]);
-	MONT_MAC(v0, v1, v2, u[5], m[5]);
-	MONT_MAC(w0, w1, w2, u[6], m[4]);
-	MONT_MAC(t0, t1, t2, u[7], m[3]);
-	MONT_MAC(v0, v1, v2, u[8], m[2]);
-	MONT_MAC(w0, w1, w2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MAC(t0, t1, t2, a[0], b[11]);
-	MONT_MUL(v0, v1, v2, a[1], b[10]);
-	MONT_MUL(w0, w1, w2, a[2], b[9]);
-	MONT_MAC(t0, t1, t2, a[3], b[8]);
-	MONT_MAC(v0, v1, v2, a[4], b[7]);
-	MONT_MAC(w0, w1, w2, a[5], b[6]);
-	MONT_MAC(t0, t1, t2, a[6], b[5]);
-	MONT_MAC(v0, v1, v2, a[7], b[4]);
-	MONT_MAC(w0, w1, w2, a[8], b[3]);
-	MONT_MAC(t0, t1, t2, a[9], b[2]);
-	MONT_MAC(v0, v1, v2, a[10], b[1]);
-	MONT_MAC(w0, w1, w2, a[11], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MAC(v0, v1, v2, u[1], m[10]);
-	MONT_MAC(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MAC(t0, t1, t2, a[0], b[12]);
-	MONT_MUL(v0, v1, v2, a[1], b[11]);
-	MONT_MUL(w0, w1, w2, a[2], b[10]);
-	MONT_MAC(t0, t1, t2, a[3], b[9]);
-	MONT_MAC(v0, v1, v2, a[4], b[8]);
-	MONT_MAC(w0, w1, w2, a[5], b[7]);
-	MONT_MAC(t0, t1, t2, a[6], b[6]);
-	MONT_MAC(v0, v1, v2, a[7], b[5]);
-	MONT_MAC(w0, w1, w2, a[8], b[4]);
-	MONT_MAC(t0, t1, t2, a[9], b[3]);
-	MONT_MAC(v0, v1, v2, a[10], b[2]);
-	MONT_MAC(w0, w1, w2, a[11], b[1]);
-	MONT_MAC(t0, t1, t2, a[12], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[12]);
-	MONT_MAC(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MAC(t0, t1, t2, a[0], b[13]);
-	MONT_MUL(v0, v1, v2, a[1], b[12]);
-	MONT_MUL(w0, w1, w2, a[2], b[11]);
-	MONT_MAC(t0, t1, t2, a[3], b[10]);
-	MONT_MAC(v0, v1, v2, a[4], b[9]);
-	MONT_MAC(w0, w1, w2, a[5], b[8]);
-	MONT_MAC(t0, t1, t2, a[6], b[7]);
-	MONT_MAC(v0, v1, v2, a[7], b[6]);
-	MONT_MAC(w0, w1, w2, a[8], b[5]);
-	MONT_MAC(t0, t1, t2, a[9], b[4]);
-	MONT_MAC(v0, v1, v2, a[10], b[3]);
-	MONT_MAC(w0, w1, w2, a[11], b[2]);
-	MONT_MAC(t0, t1, t2, a[12], b[1]);
-	MONT_MAC(v0, v1, v2, a[13], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[13]);
-	MONT_MAC(t0, t1, t2, u[1], m[12]);
-	MONT_MAC(v0, v1, v2, u[2], m[11]);
-	MONT_MAC(w0, w1, w2, u[3], m[10]);
-	MONT_MAC(t0, t1, t2, u[4], m[9]);
-	MONT_MAC(v0, v1, v2, u[5], m[8]);
-	MONT_MAC(w0, w1, w2, u[6], m[7]);
-	MONT_MAC(t0, t1, t2, u[7], m[6]);
-	MONT_MAC(v0, v1, v2, u[8], m[5]);
-	MONT_MAC(w0, w1, w2, u[9], m[4]);
-	MONT_MAC(t0, t1, t2, u[10], m[3]);
-	MONT_MAC(v0, v1, v2, u[11], m[2]);
-	MONT_MAC(w0, w1, w2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MAC(t0, t1, t2, a[0], b[14]);
-	MONT_MUL(v0, v1, v2, a[1], b[13]);
-	MONT_MUL(w0, w1, w2, a[2], b[12]);
-	MONT_MAC(t0, t1, t2, a[3], b[11]);
-	MONT_MAC(v0, v1, v2, a[4], b[10]);
-	MONT_MAC(w0, w1, w2, a[5], b[9]);
-	MONT_MAC(t0, t1, t2, a[6], b[8]);
-	MONT_MAC(v0, v1, v2, a[7], b[7]);
-	MONT_MAC(w0, w1, w2, a[8], b[6]);
-	MONT_MAC(t0, t1, t2, a[9], b[5]);
-	MONT_MAC(v0, v1, v2, a[10], b[4]);
-	MONT_MAC(w0, w1, w2, a[11], b[3]);
-	MONT_MAC(t0, t1, t2, a[12], b[2]);
-	MONT_MAC(v0, v1, v2, a[13], b[1]);
-	MONT_MAC(w0, w1, w2, a[14], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[14]);
-	MONT_MAC(v0, v1, v2, u[1], m[13]);
-	MONT_MAC(w0, w1, w2, u[2], m[12]);
-	MONT_MAC(t0, t1, t2, u[3], m[11]);
-	MONT_MAC(v0, v1, v2, u[4], m[10]);
-	MONT_MAC(w0, w1, w2, u[5], m[9]);
-	MONT_MAC(t0, t1, t2, u[6], m[8]);
-	MONT_MAC(v0, v1, v2, u[7], m[7]);
-	MONT_MAC(w0, w1, w2, u[8], m[6]);
-	MONT_MAC(t0, t1, t2, u[9], m[5]);
-	MONT_MAC(v0, v1, v2, u[10], m[4]);
-	MONT_MAC(w0, w1, w2, u[11], m[3]);
-	MONT_MAC(t0, t1, t2, u[12], m[2]);
-	MONT_MAC(v0, v1, v2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MAC(t0, t1, t2, a[0], b[15]);
-	MONT_MUL(v0, v1, v2, a[1], b[14]);
-	MONT_MUL(w0, w1, w2, a[2], b[13]);
-	MONT_MAC(t0, t1, t2, a[3], b[12]);
-	MONT_MAC(v0, v1, v2, a[4], b[11]);
-	MONT_MAC(w0, w1, w2, a[5], b[10]);
-	MONT_MAC(t0, t1, t2, a[6], b[9]);
-	MONT_MAC(v0, v1, v2, a[7], b[8]);
-	MONT_MAC(w0, w1, w2, a[8], b[7]);
-	MONT_MAC(t0, t1, t2, a[9], b[6]);
-	MONT_MAC(v0, v1, v2, a[10], b[5]);
-	MONT_MAC(w0, w1, w2, a[11], b[4]);
-	MONT_MAC(t0, t1, t2, a[12], b[3]);
-	MONT_MAC(v0, v1, v2, a[13], b[2]);
-	MONT_MAC(w0, w1, w2, a[14], b[1]);
-	MONT_MAC(t0, t1, t2, a[15], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[15]);
-	MONT_MAC(w0, w1, w2, u[1], m[14]);
-	MONT_MAC(t0, t1, t2, u[2], m[13]);
-	MONT_MAC(v0, v1, v2, u[3], m[12]);
-	MONT_MAC(w0, w1, w2, u[4], m[11]);
-	MONT_MAC(t0, t1, t2, u[5], m[10]);
-	MONT_MAC(v0, v1, v2, u[6], m[9]);
-	MONT_MAC(w0, w1, w2, u[7], m[8]);
-	MONT_MAC(t0, t1, t2, u[8], m[7]);
-	MONT_MAC(v0, v1, v2, u[9], m[6]);
-	MONT_MAC(w0, w1, w2, u[10], m[5]);
-	MONT_MAC(t0, t1, t2, u[11], m[4]);
-	MONT_MAC(v0, v1, v2, u[12], m[3]);
-	MONT_MAC(w0, w1, w2, u[13], m[2]);
-	MONT_MAC(t0, t1, t2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MAC(t0, t1, t2, a[0], b[16]);
-	MONT_MUL(v0, v1, v2, a[1], b[15]);
-	MONT_MUL(w0, w1, w2, a[2], b[14]);
-	MONT_MAC(t0, t1, t2, a[3], b[13]);
-	MONT_MAC(v0, v1, v2, a[4], b[12]);
-	MONT_MAC(w0, w1, w2, a[5], b[11]);
-	MONT_MAC(t0, t1, t2, a[6], b[10]);
-	MONT_MAC(v0, v1, v2, a[7], b[9]);
-	MONT_MAC(w0, w1, w2, a[8], b[8]);
-	MONT_MAC(t0, t1, t2, a[9], b[7]);
-	MONT_MAC(v0, v1, v2, a[10], b[6]);
-	MONT_MAC(w0, w1, w2, a[11], b[5]);
-	MONT_MAC(t0, t1, t2, a[12], b[4]);
-	MONT_MAC(v0, v1, v2, a[13], b[3]);
-	MONT_MAC(w0, w1, w2, a[14], b[2]);
-	MONT_MAC(t0, t1, t2, a[15], b[1]);
-	MONT_MAC(v0, v1, v2, a[16], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[16]);
-	MONT_MAC(t0, t1, t2, u[1], m[15]);
-	MONT_MAC(v0, v1, v2, u[2], m[14]);
-	MONT_MAC(w0, w1, w2, u[3], m[13]);
-	MONT_MAC(t0, t1, t2, u[4], m[12]);
-	MONT_MAC(v0, v1, v2, u[5], m[11]);
-	MONT_MAC(w0, w1, w2, u[6], m[10]);
-	MONT_MAC(t0, t1, t2, u[7], m[9]);
-	MONT_MAC(v0, v1, v2, u[8], m[8]);
-	MONT_MAC(w0, w1, w2, u[9], m[7]);
-	MONT_MAC(t0, t1, t2, u[10], m[6]);
-	MONT_MAC(v0, v1, v2, u[11], m[5]);
-	MONT_MAC(w0, w1, w2, u[12], m[4]);
-	MONT_MAC(t0, t1, t2, u[13], m[3]);
-	MONT_MAC(v0, v1, v2, u[14], m[2]);
-	MONT_MAC(w0, w1, w2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[16] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[16], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MAC(t0, t1, t2, a[0], b[17]);
-	MONT_MUL(v0, v1, v2, a[1], b[16]);
-	MONT_MUL(w0, w1, w2, a[2], b[15]);
-	MONT_MAC(t0, t1, t2, a[3], b[14]);
-	MONT_MAC(v0, v1, v2, a[4], b[13]);
-	MONT_MAC(w0, w1, w2, a[5], b[12]);
-	MONT_MAC(t0, t1, t2, a[6], b[11]);
-	MONT_MAC(v0, v1, v2, a[7], b[10]);
-	MONT_MAC(w0, w1, w2, a[8], b[9]);
-	MONT_MAC(t0, t1, t2, a[9], b[8]);
-	MONT_MAC(v0, v1, v2, a[10], b[7]);
-	MONT_MAC(w0, w1, w2, a[11], b[6]);
-	MONT_MAC(t0, t1, t2, a[12], b[5]);
-	MONT_MAC(v0, v1, v2, a[13], b[4]);
-	MONT_MAC(w0, w1, w2, a[14], b[3]);
-	MONT_MAC(t0, t1, t2, a[15], b[2]);
-	MONT_MAC(v0, v1, v2, a[16], b[1]);
-	MONT_MAC(w0, w1, w2, a[17], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[17]);
-	MONT_MAC(v0, v1, v2, u[1], m[16]);
-	MONT_MAC(w0, w1, w2, u[2], m[15]);
-	MONT_MAC(t0, t1, t2, u[3], m[14]);
-	MONT_MAC(v0, v1, v2, u[4], m[13]);
-	MONT_MAC(w0, w1, w2, u[5], m[12]);
-	MONT_MAC(t0, t1, t2, u[6], m[11]);
-	MONT_MAC(v0, v1, v2, u[7], m[10]);
-	MONT_MAC(w0, w1, w2, u[8], m[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[8]);
-	MONT_MAC(v0, v1, v2, u[10], m[7]);
-	MONT_MAC(w0, w1, w2, u[11], m[6]);
-	MONT_MAC(t0, t1, t2, u[12], m[5]);
-	MONT_MAC(v0, v1, v2, u[13], m[4]);
-	MONT_MAC(w0, w1, w2, u[14], m[3]);
-	MONT_MAC(t0, t1, t2, u[15], m[2]);
-	MONT_MAC(v0, v1, v2, u[16], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[17] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[17], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MAC(t0, t1, t2, a[0], b[18]);
-	MONT_MUL(v0, v1, v2, a[1], b[17]);
-	MONT_MUL(w0, w1, w2, a[2], b[16]);
-	MONT_MAC(t0, t1, t2, a[3], b[15]);
-	MONT_MAC(v0, v1, v2, a[4], b[14]);
-	MONT_MAC(w0, w1, w2, a[5], b[13]);
-	MONT_MAC(t0, t1, t2, a[6], b[12]);
-	MONT_MAC(v0, v1, v2, a[7], b[11]);
-	MONT_MAC(w0, w1, w2, a[8], b[10]);
-	MONT_MAC(t0, t1, t2, a[9], b[9]);
-	MONT_MAC(v0, v1, v2, a[10], b[8]);
-	MONT_MAC(w0, w1, w2, a[11], b[7]);
-	MONT_MAC(t0, t1, t2, a[12], b[6]);
-	MONT_MAC(v0, v1, v2, a[13], b[5]);
-	MONT_MAC(w0, w1, w2, a[14], b[4]);
-	MONT_MAC(t0, t1, t2, a[15], b[3]);
-	MONT_MAC(v0, v1, v2, a[16], b[2]);
-	MONT_MAC(w0, w1, w2, a[17], b[1]);
-	MONT_MAC(t0, t1, t2, a[18], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[18]);
-	MONT_MAC(w0, w1, w2, u[1], m[17]);
-	MONT_MAC(t0, t1, t2, u[2], m[16]);
-	MONT_MAC(v0, v1, v2, u[3], m[15]);
-	MONT_MAC(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_MAC(w0, w1, w2, u[16], m[2]);
-	MONT_MAC(t0, t1, t2, u[17], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[18] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[18], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MAC(t0, t1, t2, a[0], b[19]);
-	MONT_MUL(v0, v1, v2, a[1], b[18]);
-	MONT_MUL(w0, w1, w2, a[2], b[17]);
-	MONT_MAC(t0, t1, t2, a[3], b[16]);
-	MONT_MAC(v0, v1, v2, a[4], b[15]);
-	MONT_MAC(w0, w1, w2, a[5], b[14]);
-	MONT_MAC(t0, t1, t2, a[6], b[13]);
-	MONT_MAC(v0, v1, v2, a[7], b[12]);
-	MONT_MAC(w0, w1, w2, a[8], b[11]);
-	MONT_MAC(t0, t1, t2, a[9], b[10]);
-	MONT_MAC(v0, v1, v2, a[10], b[9]);
-	MONT_MAC(w0, w1, w2, a[11], b[8]);
-	MONT_MAC(t0, t1, t2, a[12], b[7]);
-	MONT_MAC(v0, v1, v2, a[13], b[6]);
-	MONT_MAC(w0, w1, w2, a[14], b[5]);
-	MONT_MAC(t0, t1, t2, a[15], b[4]);
-	MONT_MAC(v0, v1, v2, a[16], b[3]);
-	MONT_MAC(w0, w1, w2, a[17], b[2]);
-	MONT_MAC(t0, t1, t2, a[18], b[1]);
-	MONT_MAC(v0, v1, v2, a[19], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[19]);
-	MONT_MAC(t0, t1, t2, u[1], m[18]);
-	MONT_MAC(v0, v1, v2, u[2], m[17]);
-	MONT_MAC(w0, w1, w2, u[3], m[16]);
-	MONT_MAC(t0, t1, t2, u[4], m[15]);
-	MONT_MAC(v0, v1, v2, u[5], m[14]);
-	MONT_MAC(w0, w1, w2, u[6], m[13]);
-	MONT_MAC(t0, t1, t2, u[7], m[12]);
-	MONT_MAC(v0, v1, v2, u[8], m[11]);
-	MONT_MAC(w0, w1, w2, u[9], m[10]);
-	MONT_MAC(t0, t1, t2, u[10], m[9]);
-	MONT_MAC(v0, v1, v2, u[11], m[8]);
-	MONT_MAC(w0, w1, w2, u[12], m[7]);
-	MONT_MAC(t0, t1, t2, u[13], m[6]);
-	MONT_MAC(v0, v1, v2, u[14], m[5]);
-	MONT_MAC(w0, w1, w2, u[15], m[4]);
-	MONT_MAC(t0, t1, t2, u[16], m[3]);
-	MONT_MAC(v0, v1, v2, u[17], m[2]);
-	MONT_MAC(w0, w1, w2, u[18], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[19] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[19], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MAC(t0, t1, t2, a[0], b[20]);
-	MONT_MUL(v0, v1, v2, a[1], b[19]);
-	MONT_MUL(w0, w1, w2, a[2], b[18]);
-	MONT_MAC(t0, t1, t2, a[3], b[17]);
-	MONT_MAC(v0, v1, v2, a[4], b[16]);
-	MONT_MAC(w0, w1, w2, a[5], b[15]);
-	MONT_MAC(t0, t1, t2, a[6], b[14]);
-	MONT_MAC(v0, v1, v2, a[7], b[13]);
-	MONT_MAC(w0, w1, w2, a[8], b[12]);
-	MONT_MAC(t0, t1, t2, a[9], b[11]);
-	MONT_MAC(v0, v1, v2, a[10], b[10]);
-	MONT_MAC(w0, w1, w2, a[11], b[9]);
-	MONT_MAC(t0, t1, t2, a[12], b[8]);
-	MONT_MAC(v0, v1, v2, a[13], b[7]);
-	MONT_MAC(w0, w1, w2, a[14], b[6]);
-	MONT_MAC(t0, t1, t2, a[15], b[5]);
-	MONT_MAC(v0, v1, v2, a[16], b[4]);
-	MONT_MAC(w0, w1, w2, a[17], b[3]);
-	MONT_MAC(t0, t1, t2, a[18], b[2]);
-	MONT_MAC(v0, v1, v2, a[19], b[1]);
-	MONT_MAC(w0, w1, w2, a[20], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[20]);
-	MONT_MAC(v0, v1, v2, u[1], m[19]);
-	MONT_MAC(w0, w1, w2, u[2], m[18]);
-	MONT_MAC(t0, t1, t2, u[3], m[17]);
-	MONT_MAC(v0, v1, v2, u[4], m[16]);
-	MONT_MAC(w0, w1, w2, u[5], m[15]);
-	MONT_MAC(t0, t1, t2, u[6], m[14]);
-	MONT_MAC(v0, v1, v2, u[7], m[13]);
-	MONT_MAC(w0, w1, w2, u[8], m[12]);
-	MONT_MAC(t0, t1, t2, u[9], m[11]);
-	MONT_MAC(v0, v1, v2, u[10], m[10]);
-	MONT_MAC(w0, w1, w2, u[11], m[9]);
-	MONT_MAC(t0, t1, t2, u[12], m[8]);
-	MONT_MAC(v0, v1, v2, u[13], m[7]);
-	MONT_MAC(w0, w1, w2, u[14], m[6]);
-	MONT_MAC(t0, t1, t2, u[15], m[5]);
-	MONT_MAC(v0, v1, v2, u[16], m[4]);
-	MONT_MAC(w0, w1, w2, u[17], m[3]);
-	MONT_MAC(t0, t1, t2, u[18], m[2]);
-	MONT_MAC(v0, v1, v2, u[19], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[20] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[20], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MAC(t0, t1, t2, a[0], b[21]);
-	MONT_MUL(v0, v1, v2, a[1], b[20]);
-	MONT_MUL(w0, w1, w2, a[2], b[19]);
-	MONT_MAC(t0, t1, t2, a[3], b[18]);
-	MONT_MAC(v0, v1, v2, a[4], b[17]);
-	MONT_MAC(w0, w1, w2, a[5], b[16]);
-	MONT_MAC(t0, t1, t2, a[6], b[15]);
-	MONT_MAC(v0, v1, v2, a[7], b[14]);
-	MONT_MAC(w0, w1, w2, a[8], b[13]);
-	MONT_MAC(t0, t1, t2, a[9], b[12]);
-	MONT_MAC(v0, v1, v2, a[10], b[11]);
-	MONT_MAC(w0, w1, w2, a[11], b[10]);
-	MONT_MAC(t0, t1, t2, a[12], b[9]);
-	MONT_MAC(v0, v1, v2, a[13], b[8]);
-	MONT_MAC(w0, w1, w2, a[14], b[7]);
-	MONT_MAC(t0, t1, t2, a[15], b[6]);
-	MONT_MAC(v0, v1, v2, a[16], b[5]);
-	MONT_MAC(w0, w1, w2, a[17], b[4]);
-	MONT_MAC(t0, t1, t2, a[18], b[3]);
-	MONT_MAC(v0, v1, v2, a[19], b[2]);
-	MONT_MAC(w0, w1, w2, a[20], b[1]);
-	MONT_MAC(t0, t1, t2, a[21], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[21]);
-	MONT_MAC(w0, w1, w2, u[1], m[20]);
-	MONT_MAC(t0, t1, t2, u[2], m[19]);
-	MONT_MAC(v0, v1, v2, u[3], m[18]);
-	MONT_MAC(w0, w1, w2, u[4], m[17]);
-	MONT_MAC(t0, t1, t2, u[5], m[16]);
-	MONT_MAC(v0, v1, v2, u[6], m[15]);
-	MONT_MAC(w0, w1, w2, u[7], m[14]);
-	MONT_MAC(t0, t1, t2, u[8], m[13]);
-	MONT_MAC(v0, v1, v2, u[9], m[12]);
-	MONT_MAC(w0, w1, w2, u[10], m[11]);
-	MONT_MAC(t0, t1, t2, u[11], m[10]);
-	MONT_MAC(v0, v1, v2, u[12], m[9]);
-	MONT_MAC(w0, w1, w2, u[13], m[8]);
-	MONT_MAC(t0, t1, t2, u[14], m[7]);
-	MONT_MAC(v0, v1, v2, u[15], m[6]);
-	MONT_MAC(w0, w1, w2, u[16], m[5]);
-	MONT_MAC(t0, t1, t2, u[17], m[4]);
-	MONT_MAC(v0, v1, v2, u[18], m[3]);
-	MONT_MAC(w0, w1, w2, u[19], m[2]);
-	MONT_MAC(t0, t1, t2, u[20], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[21] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[21], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MAC(t0, t1, t2, a[0], b[22]);
-	MONT_MUL(v0, v1, v2, a[1], b[21]);
-	MONT_MUL(w0, w1, w2, a[2], b[20]);
-	MONT_MAC(t0, t1, t2, a[3], b[19]);
-	MONT_MAC(v0, v1, v2, a[4], b[18]);
-	MONT_MAC(w0, w1, w2, a[5], b[17]);
-	MONT_MAC(t0, t1, t2, a[6], b[16]);
-	MONT_MAC(v0, v1, v2, a[7], b[15]);
-	MONT_MAC(w0, w1, w2, a[8], b[14]);
-	MONT_MAC(t0, t1, t2, a[9], b[13]);
-	MONT_MAC(v0, v1, v2, a[10], b[12]);
-	MONT_MAC(w0, w1, w2, a[11], b[11]);
-	MONT_MAC(t0, t1, t2, a[12], b[10]);
-	MONT_MAC(v0, v1, v2, a[13], b[9]);
-	MONT_MAC(w0, w1, w2, a[14], b[8]);
-	MONT_MAC(t0, t1, t2, a[15], b[7]);
-	MONT_MAC(v0, v1, v2, a[16], b[6]);
-	MONT_MAC(w0, w1, w2, a[17], b[5]);
-	MONT_MAC(t0, t1, t2, a[18], b[4]);
-	MONT_MAC(v0, v1, v2, a[19], b[3]);
-	MONT_MAC(w0, w1, w2, a[20], b[2]);
-	MONT_MAC(t0, t1, t2, a[21], b[1]);
-	MONT_MAC(v0, v1, v2, a[22], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[22]);
-	MONT_MAC(t0, t1, t2, u[1], m[21]);
-	MONT_MAC(v0, v1, v2, u[2], m[20]);
-	MONT_MAC(w0, w1, w2, u[3], m[19]);
-	MONT_MAC(t0, t1, t2, u[4], m[18]);
-	MONT_MAC(v0, v1, v2, u[5], m[17]);
-	MONT_MAC(w0, w1, w2, u[6], m[16]);
-	MONT_MAC(t0, t1, t2, u[7], m[15]);
-	MONT_MAC(v0, v1, v2, u[8], m[14]);
-	MONT_MAC(w0, w1, w2, u[9], m[13]);
-	MONT_MAC(t0, t1, t2, u[10], m[12]);
-	MONT_MAC(v0, v1, v2, u[11], m[11]);
-	MONT_MAC(w0, w1, w2, u[12], m[10]);
-	MONT_MAC(t0, t1, t2, u[13], m[9]);
-	MONT_MAC(v0, v1, v2, u[14], m[8]);
-	MONT_MAC(w0, w1, w2, u[15], m[7]);
-	MONT_MAC(t0, t1, t2, u[16], m[6]);
-	MONT_MAC(v0, v1, v2, u[17], m[5]);
-	MONT_MAC(w0, w1, w2, u[18], m[4]);
-	MONT_MAC(t0, t1, t2, u[19], m[3]);
-	MONT_MAC(v0, v1, v2, u[20], m[2]);
-	MONT_MAC(w0, w1, w2, u[21], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[22] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[22], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MAC(t0, t1, t2, a[0], b[23]);
-	MONT_MUL(v0, v1, v2, a[1], b[22]);
-	MONT_MUL(w0, w1, w2, a[2], b[21]);
-	MONT_MAC(t0, t1, t2, a[3], b[20]);
-	MONT_MAC(v0, v1, v2, a[4], b[19]);
-	MONT_MAC(w0, w1, w2, a[5], b[18]);
-	MONT_MAC(t0, t1, t2, a[6], b[17]);
-	MONT_MAC(v0, v1, v2, a[7], b[16]);
-	MONT_MAC(w0, w1, w2, a[8], b[15]);
-	MONT_MAC(t0, t1, t2, a[9], b[14]);
-	MONT_MAC(v0, v1, v2, a[10], b[13]);
-	MONT_MAC(w0, w1, w2, a[11], b[12]);
-	MONT_MAC(t0, t1, t2, a[12], b[11]);
-	MONT_MAC(v0, v1, v2, a[13], b[10]);
-	MONT_MAC(w0, w1, w2, a[14], b[9]);
-	MONT_MAC(t0, t1, t2, a[15], b[8]);
-	MONT_MAC(v0, v1, v2, a[16], b[7]);
-	MONT_MAC(w0, w1, w2, a[17], b[6]);
-	MONT_MAC(t0, t1, t2, a[18], b[5]);
-	MONT_MAC(v0, v1, v2, a[19], b[4]);
-	MONT_MAC(w0, w1, w2, a[20], b[3]);
-	MONT_MAC(t0, t1, t2, a[21], b[2]);
-	MONT_MAC(v0, v1, v2, a[22], b[1]);
-	MONT_MAC(w0, w1, w2, a[23], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[23]);
-	MONT_MAC(v0, v1, v2, u[1], m[22]);
-	MONT_MAC(w0, w1, w2, u[2], m[21]);
-	MONT_MAC(t0, t1, t2, u[3], m[20]);
-	MONT_MAC(v0, v1, v2, u[4], m[19]);
-	MONT_MAC(w0, w1, w2, u[5], m[18]);
-	MONT_MAC(t0, t1, t2, u[6], m[17]);
-	MONT_MAC(v0, v1, v2, u[7], m[16]);
-	MONT_MAC(w0, w1, w2, u[8], m[15]);
-	MONT_MAC(t0, t1, t2, u[9], m[14]);
-	MONT_MAC(v0, v1, v2, u[10], m[13]);
-	MONT_MAC(w0, w1, w2, u[11], m[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[11]);
-	MONT_MAC(v0, v1, v2, u[13], m[10]);
-	MONT_MAC(w0, w1, w2, u[14], m[9]);
-	MONT_MAC(t0, t1, t2, u[15], m[8]);
-	MONT_MAC(v0, v1, v2, u[16], m[7]);
-	MONT_MAC(w0, w1, w2, u[17], m[6]);
-	MONT_MAC(t0, t1, t2, u[18], m[5]);
-	MONT_MAC(v0, v1, v2, u[19], m[4]);
-	MONT_MAC(w0, w1, w2, u[20], m[3]);
-	MONT_MAC(t0, t1, t2, u[21], m[2]);
-	MONT_MAC(v0, v1, v2, u[22], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[23] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[23], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MAC(t0, t1, t2, a[0], b[24]);
-	MONT_MUL(v0, v1, v2, a[1], b[23]);
-	MONT_MUL(w0, w1, w2, a[2], b[22]);
-	MONT_MAC(t0, t1, t2, a[3], b[21]);
-	MONT_MAC(v0, v1, v2, a[4], b[20]);
-	MONT_MAC(w0, w1, w2, a[5], b[19]);
-	MONT_MAC(t0, t1, t2, a[6], b[18]);
-	MONT_MAC(v0, v1, v2, a[7], b[17]);
-	MONT_MAC(w0, w1, w2, a[8], b[16]);
-	MONT_MAC(t0, t1, t2, a[9], b[15]);
-	MONT_MAC(v0, v1, v2, a[10], b[14]);
-	MONT_MAC(w0, w1, w2, a[11], b[13]);
-	MONT_MAC(t0, t1, t2, a[12], b[12]);
-	MONT_MAC(v0, v1, v2, a[13], b[11]);
-	MONT_MAC(w0, w1, w2, a[14], b[10]);
-	MONT_MAC(t0, t1, t2, a[15], b[9]);
-	MONT_MAC(v0, v1, v2, a[16], b[8]);
-	MONT_MAC(w0, w1, w2, a[17], b[7]);
-	MONT_MAC(t0, t1, t2, a[18], b[6]);
-	MONT_MAC(v0, v1, v2, a[19], b[5]);
-	MONT_MAC(w0, w1, w2, a[20], b[4]);
-	MONT_MAC(t0, t1, t2, a[21], b[3]);
-	MONT_MAC(v0, v1, v2, a[22], b[2]);
-	MONT_MAC(w0, w1, w2, a[23], b[1]);
-	MONT_MAC(t0, t1, t2, a[24], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[24]);
-	MONT_MAC(w0, w1, w2, u[1], m[23]);
-	MONT_MAC(t0, t1, t2, u[2], m[22]);
-	MONT_MAC(v0, v1, v2, u[3], m[21]);
-	MONT_MAC(w0, w1, w2, u[4], m[20]);
-	MONT_MAC(t0, t1, t2, u[5], m[19]);
-	MONT_MAC(v0, v1, v2, u[6], m[18]);
-	MONT_MAC(w0, w1, w2, u[7], m[17]);
-	MONT_MAC(t0, t1, t2, u[8], m[16]);
-	MONT_MAC(v0, v1, v2, u[9], m[15]);
-	MONT_MAC(w0, w1, w2, u[10], m[14]);
-	MONT_MAC(t0, t1, t2, u[11], m[13]);
-	MONT_MAC(v0, v1, v2, u[12], m[12]);
-	MONT_MAC(w0, w1, w2, u[13], m[11]);
-	MONT_MAC(t0, t1, t2, u[14], m[10]);
-	MONT_MAC(v0, v1, v2, u[15], m[9]);
-	MONT_MAC(w0, w1, w2, u[16], m[8]);
-	MONT_MAC(t0, t1, t2, u[17], m[7]);
-	MONT_MAC(v0, v1, v2, u[18], m[6]);
-	MONT_MAC(w0, w1, w2, u[19], m[5]);
-	MONT_MAC(t0, t1, t2, u[20], m[4]);
-	MONT_MAC(v0, v1, v2, u[21], m[3]);
-	MONT_MAC(w0, w1, w2, u[22], m[2]);
-	MONT_MAC(t0, t1, t2, u[23], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[24] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[24], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MAC(t0, t1, t2, a[0], b[25]);
-	MONT_MUL(v0, v1, v2, a[1], b[24]);
-	MONT_MUL(w0, w1, w2, a[2], b[23]);
-	MONT_MAC(t0, t1, t2, a[3], b[22]);
-	MONT_MAC(v0, v1, v2, a[4], b[21]);
-	MONT_MAC(w0, w1, w2, a[5], b[20]);
-	MONT_MAC(t0, t1, t2, a[6], b[19]);
-	MONT_MAC(v0, v1, v2, a[7], b[18]);
-	MONT_MAC(w0, w1, w2, a[8], b[17]);
-	MONT_MAC(t0, t1, t2, a[9], b[16]);
-	MONT_MAC(v0, v1, v2, a[10], b[15]);
-	MONT_MAC(w0, w1, w2, a[11], b[14]);
-	MONT_MAC(t0, t1, t2, a[12], b[13]);
-	MONT_MAC(v0, v1, v2, a[13], b[12]);
-	MONT_MAC(w0, w1, w2, a[14], b[11]);
-	MONT_MAC(t0, t1, t2, a[15], b[10]);
-	MONT_MAC(v0, v1, v2, a[16], b[9]);
-	MONT_MAC(w0, w1, w2, a[17], b[8]);
-	MONT_MAC(t0, t1, t2, a[18], b[7]);
-	MONT_MAC(v0, v1, v2, a[19], b[6]);
-	MONT_MAC(w0, w1, w2, a[20], b[5]);
-	MONT_MAC(t0, t1, t2, a[21], b[4]);
-	MONT_MAC(v0, v1, v2, a[22], b[3]);
-	MONT_MAC(w0, w1, w2, a[23], b[2]);
-	MONT_MAC(t0, t1, t2, a[24], b[1]);
-	MONT_MAC(v0, v1, v2, a[25], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[25]);
-	MONT_MAC(t0, t1, t2, u[1], m[24]);
-	MONT_MAC(v0, v1, v2, u[2], m[23]);
-	MONT_MAC(w0, w1, w2, u[3], m[22]);
-	MONT_MAC(t0, t1, t2, u[4], m[21]);
-	MONT_MAC(v0, v1, v2, u[5], m[20]);
-	MONT_MAC(w0, w1, w2, u[6], m[19]);
-	MONT_MAC(t0, t1, t2, u[7], m[18]);
-	MONT_MAC(v0, v1, v2, u[8], m[17]);
-	MONT_MAC(w0, w1, w2, u[9], m[16]);
-	MONT_MAC(t0, t1, t2, u[10], m[15]);
-	MONT_MAC(v0, v1, v2, u[11], m[14]);
-	MONT_MAC(w0, w1, w2, u[12], m[13]);
-	MONT_MAC(t0, t1, t2, u[13], m[12]);
-	MONT_MAC(v0, v1, v2, u[14], m[11]);
-	MONT_MAC(w0, w1, w2, u[15], m[10]);
-	MONT_MAC(t0, t1, t2, u[16], m[9]);
-	MONT_MAC(v0, v1, v2, u[17], m[8]);
-	MONT_MAC(w0, w1, w2, u[18], m[7]);
-	MONT_MAC(t0, t1, t2, u[19], m[6]);
-	MONT_MAC(v0, v1, v2, u[20], m[5]);
-	MONT_MAC(w0, w1, w2, u[21], m[4]);
-	MONT_MAC(t0, t1, t2, u[22], m[3]);
-	MONT_MAC(v0, v1, v2, u[23], m[2]);
-	MONT_MAC(w0, w1, w2, u[24], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[25] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[25], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MAC(t0, t1, t2, a[0], b[26]);
-	MONT_MUL(v0, v1, v2, a[1], b[25]);
-	MONT_MUL(w0, w1, w2, a[2], b[24]);
-	MONT_MAC(t0, t1, t2, a[3], b[23]);
-	MONT_MAC(v0, v1, v2, a[4], b[22]);
-	MONT_MAC(w0, w1, w2, a[5], b[21]);
-	MONT_MAC(t0, t1, t2, a[6], b[20]);
-	MONT_MAC(v0, v1, v2, a[7], b[19]);
-	MONT_MAC(w0, w1, w2, a[8], b[18]);
-	MONT_MAC(t0, t1, t2, a[9], b[17]);
-	MONT_MAC(v0, v1, v2, a[10], b[16]);
-	MONT_MAC(w0, w1, w2, a[11], b[15]);
-	MONT_MAC(t0, t1, t2, a[12], b[14]);
-	MONT_MAC(v0, v1, v2, a[13], b[13]);
-	MONT_MAC(w0, w1, w2, a[14], b[12]);
-	MONT_MAC(t0, t1, t2, a[15], b[11]);
-	MONT_MAC(v0, v1, v2, a[16], b[10]);
-	MONT_MAC(w0, w1, w2, a[17], b[9]);
-	MONT_MAC(t0, t1, t2, a[18], b[8]);
-	MONT_MAC(v0, v1, v2, a[19], b[7]);
-	MONT_MAC(w0, w1, w2, a[20], b[6]);
-	MONT_MAC(t0, t1, t2, a[21], b[5]);
-	MONT_MAC(v0, v1, v2, a[22], b[4]);
-	MONT_MAC(w0, w1, w2, a[23], b[3]);
-	MONT_MAC(t0, t1, t2, a[24], b[2]);
-	MONT_MAC(v0, v1, v2, a[25], b[1]);
-	MONT_MAC(w0, w1, w2, a[26], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[26]);
-	MONT_MAC(v0, v1, v2, u[1], m[25]);
-	MONT_MAC(w0, w1, w2, u[2], m[24]);
-	MONT_MAC(t0, t1, t2, u[3], m[23]);
-	MONT_MAC(v0, v1, v2, u[4], m[22]);
-	MONT_MAC(w0, w1, w2, u[5], m[21]);
-	MONT_MAC(t0, t1, t2, u[6], m[20]);
-	MONT_MAC(v0, v1, v2, u[7], m[19]);
-	MONT_MAC(w0, w1, w2, u[8], m[18]);
-	MONT_MAC(t0, t1, t2, u[9], m[17]);
-	MONT_MAC(v0, v1, v2, u[10], m[16]);
-	MONT_MAC(w0, w1, w2, u[11], m[15]);
-	MONT_MAC(t0, t1, t2, u[12], m[14]);
-	MONT_MAC(v0, v1, v2, u[13], m[13]);
-	MONT_MAC(w0, w1, w2, u[14], m[12]);
-	MONT_MAC(t0, t1, t2, u[15], m[11]);
-	MONT_MAC(v0, v1, v2, u[16], m[10]);
-	MONT_MAC(w0, w1, w2, u[17], m[9]);
-	MONT_MAC(t0, t1, t2, u[18], m[8]);
-	MONT_MAC(v0, v1, v2, u[19], m[7]);
-	MONT_MAC(w0, w1, w2, u[20], m[6]);
-	MONT_MAC(t0, t1, t2, u[21], m[5]);
-	MONT_MAC(v0, v1, v2, u[22], m[4]);
-	MONT_MAC(w0, w1, w2, u[23], m[3]);
-	MONT_MAC(t0, t1, t2, u[24], m[2]);
-	MONT_MAC(v0, v1, v2, u[25], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[26] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[26], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MAC(t0, t1, t2, a[0], b[27]);
-	MONT_MUL(v0, v1, v2, a[1], b[26]);
-	MONT_MUL(w0, w1, w2, a[2], b[25]);
-	MONT_MAC(t0, t1, t2, a[3], b[24]);
-	MONT_MAC(v0, v1, v2, a[4], b[23]);
-	MONT_MAC(w0, w1, w2, a[5], b[22]);
-	MONT_MAC(t0, t1, t2, a[6], b[21]);
-	MONT_MAC(v0, v1, v2, a[7], b[20]);
-	MONT_MAC(w0, w1, w2, a[8], b[19]);
-	MONT_MAC(t0, t1, t2, a[9], b[18]);
-	MONT_MAC(v0, v1, v2, a[10], b[17]);
-	MONT_MAC(w0, w1, w2, a[11], b[16]);
-	MONT_MAC(t0, t1, t2, a[12], b[15]);
-	MONT_MAC(v0, v1, v2, a[13], b[14]);
-	MONT_MAC(w0, w1, w2, a[14], b[13]);
-	MONT_MAC(t0, t1, t2, a[15], b[12]);
-	MONT_MAC(v0, v1, v2, a[16], b[11]);
-	MONT_MAC(w0, w1, w2, a[17], b[10]);
-	MONT_MAC(t0, t1, t2, a[18], b[9]);
-	MONT_MAC(v0, v1, v2, a[19], b[8]);
-	MONT_MAC(w0, w1, w2, a[20], b[7]);
-	MONT_MAC(t0, t1, t2, a[21], b[6]);
-	MONT_MAC(v0, v1, v2, a[22], b[5]);
-	MONT_MAC(w0, w1, w2, a[23], b[4]);
-	MONT_MAC(t0, t1, t2, a[24], b[3]);
-	MONT_MAC(v0, v1, v2, a[25], b[2]);
-	MONT_MAC(w0, w1, w2, a[26], b[1]);
-	MONT_MAC(t0, t1, t2, a[27], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[27]);
-	MONT_MAC(w0, w1, w2, u[1], m[26]);
-	MONT_MAC(t0, t1, t2, u[2], m[25]);
-	MONT_MAC(v0, v1, v2, u[3], m[24]);
-	MONT_MAC(w0, w1, w2, u[4], m[23]);
-	MONT_MAC(t0, t1, t2, u[5], m[22]);
-	MONT_MAC(v0, v1, v2, u[6], m[21]);
-	MONT_MAC(w0, w1, w2, u[7], m[20]);
-	MONT_MAC(t0, t1, t2, u[8], m[19]);
-	MONT_MAC(v0, v1, v2, u[9], m[18]);
-	MONT_MAC(w0, w1, w2, u[10], m[17]);
-	MONT_MAC(t0, t1, t2, u[11], m[16]);
-	MONT_MAC(v0, v1, v2, u[12], m[15]);
-	MONT_MAC(w0, w1, w2, u[13], m[14]);
-	MONT_MAC(t0, t1, t2, u[14], m[13]);
-	MONT_MAC(v0, v1, v2, u[15], m[12]);
-	MONT_MAC(w0, w1, w2, u[16], m[11]);
-	MONT_MAC(t0, t1, t2, u[17], m[10]);
-	MONT_MAC(v0, v1, v2, u[18], m[9]);
-	MONT_MAC(w0, w1, w2, u[19], m[8]);
-	MONT_MAC(t0, t1, t2, u[20], m[7]);
-	MONT_MAC(v0, v1, v2, u[21], m[6]);
-	MONT_MAC(w0, w1, w2, u[22], m[5]);
-	MONT_MAC(t0, t1, t2, u[23], m[4]);
-	MONT_MAC(v0, v1, v2, u[24], m[3]);
-	MONT_MAC(w0, w1, w2, u[25], m[2]);
-	MONT_MAC(t0, t1, t2, u[26], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[27] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[27], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MAC(t0, t1, t2, a[0], b[28]);
-	MONT_MUL(v0, v1, v2, a[1], b[27]);
-	MONT_MUL(w0, w1, w2, a[2], b[26]);
-	MONT_MAC(t0, t1, t2, a[3], b[25]);
-	MONT_MAC(v0, v1, v2, a[4], b[24]);
-	MONT_MAC(w0, w1, w2, a[5], b[23]);
-	MONT_MAC(t0, t1, t2, a[6], b[22]);
-	MONT_MAC(v0, v1, v2, a[7], b[21]);
-	MONT_MAC(w0, w1, w2, a[8], b[20]);
-	MONT_MAC(t0, t1, t2, a[9], b[19]);
-	MONT_MAC(v0, v1, v2, a[10], b[18]);
-	MONT_MAC(w0, w1, w2, a[11], b[17]);
-	MONT_MAC(t0, t1, t2, a[12], b[16]);
-	MONT_MAC(v0, v1, v2, a[13], b[15]);
-	MONT_MAC(w0, w1, w2, a[14], b[14]);
-	MONT_MAC(t0, t1, t2, a[15], b[13]);
-	MONT_MAC(v0, v1, v2, a[16], b[12]);
-	MONT_MAC(w0, w1, w2, a[17], b[11]);
-	MONT_MAC(t0, t1, t2, a[18], b[10]);
-	MONT_MAC(v0, v1, v2, a[19], b[9]);
-	MONT_MAC(w0, w1, w2, a[20], b[8]);
-	MONT_MAC(t0, t1, t2, a[21], b[7]);
-	MONT_MAC(v0, v1, v2, a[22], b[6]);
-	MONT_MAC(w0, w1, w2, a[23], b[5]);
-	MONT_MAC(t0, t1, t2, a[24], b[4]);
-	MONT_MAC(v0, v1, v2, a[25], b[3]);
-	MONT_MAC(w0, w1, w2, a[26], b[2]);
-	MONT_MAC(t0, t1, t2, a[27], b[1]);
-	MONT_MAC(v0, v1, v2, a[28], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[28]);
-	MONT_MAC(t0, t1, t2, u[1], m[27]);
-	MONT_MAC(v0, v1, v2, u[2], m[26]);
-	MONT_MAC(w0, w1, w2, u[3], m[25]);
-	MONT_MAC(t0, t1, t2, u[4], m[24]);
-	MONT_MAC(v0, v1, v2, u[5], m[23]);
-	MONT_MAC(w0, w1, w2, u[6], m[22]);
-	MONT_MAC(t0, t1, t2, u[7], m[21]);
-	MONT_MAC(v0, v1, v2, u[8], m[20]);
-	MONT_MAC(w0, w1, w2, u[9], m[19]);
-	MONT_MAC(t0, t1, t2, u[10], m[18]);
-	MONT_MAC(v0, v1, v2, u[11], m[17]);
-	MONT_MAC(w0, w1, w2, u[12], m[16]);
-	MONT_MAC(t0, t1, t2, u[13], m[15]);
-	MONT_MAC(v0, v1, v2, u[14], m[14]);
-	MONT_MAC(w0, w1, w2, u[15], m[13]);
-	MONT_MAC(t0, t1, t2, u[16], m[12]);
-	MONT_MAC(v0, v1, v2, u[17], m[11]);
-	MONT_MAC(w0, w1, w2, u[18], m[10]);
-	MONT_MAC(t0, t1, t2, u[19], m[9]);
-	MONT_MAC(v0, v1, v2, u[20], m[8]);
-	MONT_MAC(w0, w1, w2, u[21], m[7]);
-	MONT_MAC(t0, t1, t2, u[22], m[6]);
-	MONT_MAC(v0, v1, v2, u[23], m[5]);
-	MONT_MAC(w0, w1, w2, u[24], m[4]);
-	MONT_MAC(t0, t1, t2, u[25], m[3]);
-	MONT_MAC(v0, v1, v2, u[26], m[2]);
-	MONT_MAC(w0, w1, w2, u[27], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[28] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[28], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MAC(t0, t1, t2, a[0], b[29]);
-	MONT_MUL(v0, v1, v2, a[1], b[28]);
-	MONT_MUL(w0, w1, w2, a[2], b[27]);
-	MONT_MAC(t0, t1, t2, a[3], b[26]);
-	MONT_MAC(v0, v1, v2, a[4], b[25]);
-	MONT_MAC(w0, w1, w2, a[5], b[24]);
-	MONT_MAC(t0, t1, t2, a[6], b[23]);
-	MONT_MAC(v0, v1, v2, a[7], b[22]);
-	MONT_MAC(w0, w1, w2, a[8], b[21]);
-	MONT_MAC(t0, t1, t2, a[9], b[20]);
-	MONT_MAC(v0, v1, v2, a[10], b[19]);
-	MONT_MAC(w0, w1, w2, a[11], b[18]);
-	MONT_MAC(t0, t1, t2, a[12], b[17]);
-	MONT_MAC(v0, v1, v2, a[13], b[16]);
-	MONT_MAC(w0, w1, w2, a[14], b[15]);
-	MONT_MAC(t0, t1, t2, a[15], b[14]);
-	MONT_MAC(v0, v1, v2, a[16], b[13]);
-	MONT_MAC(w0, w1, w2, a[17], b[12]);
-	MONT_MAC(t0, t1, t2, a[18], b[11]);
-	MONT_MAC(v0, v1, v2, a[19], b[10]);
-	MONT_MAC(w0, w1, w2, a[20], b[9]);
-	MONT_MAC(t0, t1, t2, a[21], b[8]);
-	MONT_MAC(v0, v1, v2, a[22], b[7]);
-	MONT_MAC(w0, w1, w2, a[23], b[6]);
-	MONT_MAC(t0, t1, t2, a[24], b[5]);
-	MONT_MAC(v0, v1, v2, a[25], b[4]);
-	MONT_MAC(w0, w1, w2, a[26], b[3]);
-	MONT_MAC(t0, t1, t2, a[27], b[2]);
-	MONT_MAC(v0, v1, v2, a[28], b[1]);
-	MONT_MAC(w0, w1, w2, a[29], b[0]);
-	MONT_MAC(t0, t1, t2, u[0], m[29]);
-	MONT_MAC(v0, v1, v2, u[1], m[28]);
-	MONT_MAC(w0, w1, w2, u[2], m[27]);
-	MONT_MAC(t0, t1, t2, u[3], m[26]);
-	MONT_MAC(v0, v1, v2, u[4], m[25]);
-	MONT_MAC(w0, w1, w2, u[5], m[24]);
-	MONT_MAC(t0, t1, t2, u[6], m[23]);
-	MONT_MAC(v0, v1, v2, u[7], m[22]);
-	MONT_MAC(w0, w1, w2, u[8], m[21]);
-	MONT_MAC(t0, t1, t2, u[9], m[20]);
-	MONT_MAC(v0, v1, v2, u[10], m[19]);
-	MONT_MAC(w0, w1, w2, u[11], m[18]);
-	MONT_MAC(t0, t1, t2, u[12], m[17]);
-	MONT_MAC(v0, v1, v2, u[13], m[16]);
-	MONT_MAC(w0, w1, w2, u[14], m[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[14]);
-	MONT_MAC(v0, v1, v2, u[16], m[13]);
-	MONT_MAC(w0, w1, w2, u[17], m[12]);
-	MONT_MAC(t0, t1, t2, u[18], m[11]);
-	MONT_MAC(v0, v1, v2, u[19], m[10]);
-	MONT_MAC(w0, w1, w2, u[20], m[9]);
-	MONT_MAC(t0, t1, t2, u[21], m[8]);
-	MONT_MAC(v0, v1, v2, u[22], m[7]);
-	MONT_MAC(w0, w1, w2, u[23], m[6]);
-	MONT_MAC(t0, t1, t2, u[24], m[5]);
-	MONT_MAC(v0, v1, v2, u[25], m[4]);
-	MONT_MAC(w0, w1, w2, u[26], m[3]);
-	MONT_MAC(t0, t1, t2, u[27], m[2]);
-	MONT_MAC(v0, v1, v2, u[28], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[29] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[29], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MAC(t0, t1, t2, a[0], b[30]);
-	MONT_MUL(v0, v1, v2, a[1], b[29]);
-	MONT_MUL(w0, w1, w2, a[2], b[28]);
-	MONT_MAC(t0, t1, t2, a[3], b[27]);
-	MONT_MAC(v0, v1, v2, a[4], b[26]);
-	MONT_MAC(w0, w1, w2, a[5], b[25]);
-	MONT_MAC(t0, t1, t2, a[6], b[24]);
-	MONT_MAC(v0, v1, v2, a[7], b[23]);
-	MONT_MAC(w0, w1, w2, a[8], b[22]);
-	MONT_MAC(t0, t1, t2, a[9], b[21]);
-	MONT_MAC(v0, v1, v2, a[10], b[20]);
-	MONT_MAC(w0, w1, w2, a[11], b[19]);
-	MONT_MAC(t0, t1, t2, a[12], b[18]);
-	MONT_MAC(v0, v1, v2, a[13], b[17]);
-	MONT_MAC(w0, w1, w2, a[14], b[16]);
-	MONT_MAC(t0, t1, t2, a[15], b[15]);
-	MONT_MAC(v0, v1, v2, a[16], b[14]);
-	MONT_MAC(w0, w1, w2, a[17], b[13]);
-	MONT_MAC(t0, t1, t2, a[18], b[12]);
-	MONT_MAC(v0, v1, v2, a[19], b[11]);
-	MONT_MAC(w0, w1, w2, a[20], b[10]);
-	MONT_MAC(t0, t1, t2, a[21], b[9]);
-	MONT_MAC(v0, v1, v2, a[22], b[8]);
-	MONT_MAC(w0, w1, w2, a[23], b[7]);
-	MONT_MAC(t0, t1, t2, a[24], b[6]);
-	MONT_MAC(v0, v1, v2, a[25], b[5]);
-	MONT_MAC(w0, w1, w2, a[26], b[4]);
-	MONT_MAC(t0, t1, t2, a[27], b[3]);
-	MONT_MAC(v0, v1, v2, a[28], b[2]);
-	MONT_MAC(w0, w1, w2, a[29], b[1]);
-	MONT_MAC(t0, t1, t2, a[30], b[0]);
-	MONT_MAC(v0, v1, v2, u[0], m[30]);
-	MONT_MAC(w0, w1, w2, u[1], m[29]);
-	MONT_MAC(t0, t1, t2, u[2], m[28]);
-	MONT_MAC(v0, v1, v2, u[3], m[27]);
-	MONT_MAC(w0, w1, w2, u[4], m[26]);
-	MONT_MAC(t0, t1, t2, u[5], m[25]);
-	MONT_MAC(v0, v1, v2, u[6], m[24]);
-	MONT_MAC(w0, w1, w2, u[7], m[23]);
-	MONT_MAC(t0, t1, t2, u[8], m[22]);
-	MONT_MAC(v0, v1, v2, u[9], m[21]);
-	MONT_MAC(w0, w1, w2, u[10], m[20]);
-	MONT_MAC(t0, t1, t2, u[11], m[19]);
-	MONT_MAC(v0, v1, v2, u[12], m[18]);
-	MONT_MAC(w0, w1, w2, u[13], m[17]);
-	MONT_MAC(t0, t1, t2, u[14], m[16]);
-	MONT_MAC(v0, v1, v2, u[15], m[15]);
-	MONT_MAC(w0, w1, w2, u[16], m[14]);
-	MONT_MAC(t0, t1, t2, u[17], m[13]);
-	MONT_MAC(v0, v1, v2, u[18], m[12]);
-	MONT_MAC(w0, w1, w2, u[19], m[11]);
-	MONT_MAC(t0, t1, t2, u[20], m[10]);
-	MONT_MAC(v0, v1, v2, u[21], m[9]);
-	MONT_MAC(w0, w1, w2, u[22], m[8]);
-	MONT_MAC(t0, t1, t2, u[23], m[7]);
-	MONT_MAC(v0, v1, v2, u[24], m[6]);
-	MONT_MAC(w0, w1, w2, u[25], m[5]);
-	MONT_MAC(t0, t1, t2, u[26], m[4]);
-	MONT_MAC(v0, v1, v2, u[27], m[3]);
-	MONT_MAC(w0, w1, w2, u[28], m[2]);
-	MONT_MAC(t0, t1, t2, u[29], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[30] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[30], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 31 */
-	MONT_MAC(t0, t1, t2, a[0], b[31]);
-	MONT_MUL(v0, v1, v2, a[1], b[30]);
-	MONT_MUL(w0, w1, w2, a[2], b[29]);
-	MONT_MAC(t0, t1, t2, a[3], b[28]);
-	MONT_MAC(v0, v1, v2, a[4], b[27]);
-	MONT_MAC(w0, w1, w2, a[5], b[26]);
-	MONT_MAC(t0, t1, t2, a[6], b[25]);
-	MONT_MAC(v0, v1, v2, a[7], b[24]);
-	MONT_MAC(w0, w1, w2, a[8], b[23]);
-	MONT_MAC(t0, t1, t2, a[9], b[22]);
-	MONT_MAC(v0, v1, v2, a[10], b[21]);
-	MONT_MAC(w0, w1, w2, a[11], b[20]);
-	MONT_MAC(t0, t1, t2, a[12], b[19]);
-	MONT_MAC(v0, v1, v2, a[13], b[18]);
-	MONT_MAC(w0, w1, w2, a[14], b[17]);
-	MONT_MAC(t0, t1, t2, a[15], b[16]);
-	MONT_MAC(v0, v1, v2, a[16], b[15]);
-	MONT_MAC(w0, w1, w2, a[17], b[14]);
-	MONT_MAC(t0, t1, t2, a[18], b[13]);
-	MONT_MAC(v0, v1, v2, a[19], b[12]);
-	MONT_MAC(w0, w1, w2, a[20], b[11]);
-	MONT_MAC(t0, t1, t2, a[21], b[10]);
-	MONT_MAC(v0, v1, v2, a[22], b[9]);
-	MONT_MAC(w0, w1, w2, a[23], b[8]);
-	MONT_MAC(t0, t1, t2, a[24], b[7]);
-	MONT_MAC(v0, v1, v2, a[25], b[6]);
-	MONT_MAC(w0, w1, w2, a[26], b[5]);
-	MONT_MAC(t0, t1, t2, a[27], b[4]);
-	MONT_MAC(v0, v1, v2, a[28], b[3]);
-	MONT_MAC(w0, w1, w2, a[29], b[2]);
-	MONT_MAC(t0, t1, t2, a[30], b[1]);
-	MONT_MAC(v0, v1, v2, a[31], b[0]);
-	MONT_MAC(w0, w1, w2, u[0], m[31]);
-	MONT_MAC(t0, t1, t2, u[1], m[30]);
-	MONT_MAC(v0, v1, v2, u[2], m[29]);
-	MONT_MAC(w0, w1, w2, u[3], m[28]);
-	MONT_MAC(t0, t1, t2, u[4], m[27]);
-	MONT_MAC(v0, v1, v2, u[5], m[26]);
-	MONT_MAC(w0, w1, w2, u[6], m[25]);
-	MONT_MAC(t0, t1, t2, u[7], m[24]);
-	MONT_MAC(v0, v1, v2, u[8], m[23]);
-	MONT_MAC(w0, w1, w2, u[9], m[22]);
-	MONT_MAC(t0, t1, t2, u[10], m[21]);
-	MONT_MAC(v0, v1, v2, u[11], m[20]);
-	MONT_MAC(w0, w1, w2, u[12], m[19]);
-	MONT_MAC(t0, t1, t2, u[13], m[18]);
-	MONT_MAC(v0, v1, v2, u[14], m[17]);
-	MONT_MAC(w0, w1, w2, u[15], m[16]);
-	MONT_MAC(t0, t1, t2, u[16], m[15]);
-	MONT_MAC(v0, v1, v2, u[17], m[14]);
-	MONT_MAC(w0, w1, w2, u[18], m[13]);
-	MONT_MAC(t0, t1, t2, u[19], m[12]);
-	MONT_MAC(v0, v1, v2, u[20], m[11]);
-	MONT_MAC(w0, w1, w2, u[21], m[10]);
-	MONT_MAC(t0, t1, t2, u[22], m[9]);
-	MONT_MAC(v0, v1, v2, u[23], m[8]);
-	MONT_MAC(w0, w1, w2, u[24], m[7]);
-	MONT_MAC(t0, t1, t2, u[25], m[6]);
-	MONT_MAC(v0, v1, v2, u[26], m[5]);
-	MONT_MAC(w0, w1, w2, u[27], m[4]);
-	MONT_MAC(t0, t1, t2, u[28], m[3]);
-	MONT_MAC(v0, v1, v2, u[29], m[2]);
-	MONT_MAC(w0, w1, w2, u[30], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	u[31] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[31], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 32 */
-	MONT_MAC(t0, t1, t2, a[1], b[31]);
-	MONT_MUL(v0, v1, v2, a[2], b[30]);
-	MONT_MUL(w0, w1, w2, a[3], b[29]);
-	MONT_MAC(t0, t1, t2, a[4], b[28]);
-	MONT_MAC(v0, v1, v2, a[5], b[27]);
-	MONT_MAC(w0, w1, w2, a[6], b[26]);
-	MONT_MAC(t0, t1, t2, a[7], b[25]);
-	MONT_MAC(v0, v1, v2, a[8], b[24]);
-	MONT_MAC(w0, w1, w2, a[9], b[23]);
-	MONT_MAC(t0, t1, t2, a[10], b[22]);
-	MONT_MAC(v0, v1, v2, a[11], b[21]);
-	MONT_MAC(w0, w1, w2, a[12], b[20]);
-	MONT_MAC(t0, t1, t2, a[13], b[19]);
-	MONT_MAC(v0, v1, v2, a[14], b[18]);
-	MONT_MAC(w0, w1, w2, a[15], b[17]);
-	MONT_MAC(t0, t1, t2, a[16], b[16]);
-	MONT_MAC(v0, v1, v2, a[17], b[15]);
-	MONT_MAC(w0, w1, w2, a[18], b[14]);
-	MONT_MAC(t0, t1, t2, a[19], b[13]);
-	MONT_MAC(v0, v1, v2, a[20], b[12]);
-	MONT_MAC(w0, w1, w2, a[21], b[11]);
-	MONT_MAC(t0, t1, t2, a[22], b[10]);
-	MONT_MAC(v0, v1, v2, a[23], b[9]);
-	MONT_MAC(w0, w1, w2, a[24], b[8]);
-	MONT_MAC(t0, t1, t2, a[25], b[7]);
-	MONT_MAC(v0, v1, v2, a[26], b[6]);
-	MONT_MAC(w0, w1, w2, a[27], b[5]);
-	MONT_MAC(t0, t1, t2, a[28], b[4]);
-	MONT_MAC(v0, v1, v2, a[29], b[3]);
-	MONT_MAC(w0, w1, w2, a[30], b[2]);
-	MONT_MAC(t0, t1, t2, a[31], b[1]);
-	MONT_MAC(v0, v1, v2, u[1], m[31]);
-	MONT_MAC(w0, w1, w2, u[2], m[30]);
-	MONT_MAC(t0, t1, t2, u[3], m[29]);
-	MONT_MAC(v0, v1, v2, u[4], m[28]);
-	MONT_MAC(w0, w1, w2, u[5], m[27]);
-	MONT_MAC(t0, t1, t2, u[6], m[26]);
-	MONT_MAC(v0, v1, v2, u[7], m[25]);
-	MONT_MAC(w0, w1, w2, u[8], m[24]);
-	MONT_MAC(t0, t1, t2, u[9], m[23]);
-	MONT_MAC(v0, v1, v2, u[10], m[22]);
-	MONT_MAC(w0, w1, w2, u[11], m[21]);
-	MONT_MAC(t0, t1, t2, u[12], m[20]);
-	MONT_MAC(v0, v1, v2, u[13], m[19]);
-	MONT_MAC(w0, w1, w2, u[14], m[18]);
-	MONT_MAC(t0, t1, t2, u[15], m[17]);
-	MONT_MAC(v0, v1, v2, u[16], m[16]);
-	MONT_MAC(w0, w1, w2, u[17], m[15]);
-	MONT_MAC(t0, t1, t2, u[18], m[14]);
-	MONT_MAC(v0, v1, v2, u[19], m[13]);
-	MONT_MAC(w0, w1, w2, u[20], m[12]);
-	MONT_MAC(t0, t1, t2, u[21], m[11]);
-	MONT_MAC(v0, v1, v2, u[22], m[10]);
-	MONT_MAC(w0, w1, w2, u[23], m[9]);
-	MONT_MAC(t0, t1, t2, u[24], m[8]);
-	MONT_MAC(v0, v1, v2, u[25], m[7]);
-	MONT_MAC(w0, w1, w2, u[26], m[6]);
-	MONT_MAC(t0, t1, t2, u[27], m[5]);
-	MONT_MAC(v0, v1, v2, u[28], m[4]);
-	MONT_MAC(w0, w1, w2, u[29], m[3]);
-	MONT_MAC(t0, t1, t2, u[30], m[2]);
-	MONT_MAC(v0, v1, v2, u[31], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 33 */
-	MONT_MAC(t0, t1, t2, a[2], b[31]);
-	MONT_MUL(v0, v1, v2, a[3], b[30]);
-	MONT_MUL(w0, w1, w2, a[4], b[29]);
-	MONT_MAC(t0, t1, t2, a[5], b[28]);
-	MONT_MAC(v0, v1, v2, a[6], b[27]);
-	MONT_MAC(w0, w1, w2, a[7], b[26]);
-	MONT_MAC(t0, t1, t2, a[8], b[25]);
-	MONT_MAC(v0, v1, v2, a[9], b[24]);
-	MONT_MAC(w0, w1, w2, a[10], b[23]);
-	MONT_MAC(t0, t1, t2, a[11], b[22]);
-	MONT_MAC(v0, v1, v2, a[12], b[21]);
-	MONT_MAC(w0, w1, w2, a[13], b[20]);
-	MONT_MAC(t0, t1, t2, a[14], b[19]);
-	MONT_MAC(v0, v1, v2, a[15], b[18]);
-	MONT_MAC(w0, w1, w2, a[16], b[17]);
-	MONT_MAC(t0, t1, t2, a[17], b[16]);
-	MONT_MAC(v0, v1, v2, a[18], b[15]);
-	MONT_MAC(w0, w1, w2, a[19], b[14]);
-	MONT_MAC(t0, t1, t2, a[20], b[13]);
-	MONT_MAC(v0, v1, v2, a[21], b[12]);
-	MONT_MAC(w0, w1, w2, a[22], b[11]);
-	MONT_MAC(t0, t1, t2, a[23], b[10]);
-	MONT_MAC(v0, v1, v2, a[24], b[9]);
-	MONT_MAC(w0, w1, w2, a[25], b[8]);
-	MONT_MAC(t0, t1, t2, a[26], b[7]);
-	MONT_MAC(v0, v1, v2, a[27], b[6]);
-	MONT_MAC(w0, w1, w2, a[28], b[5]);
-	MONT_MAC(t0, t1, t2, a[29], b[4]);
-	MONT_MAC(v0, v1, v2, a[30], b[3]);
-	MONT_MAC(w0, w1, w2, a[31], b[2]);
-	MONT_MAC(t0, t1, t2, u[2], m[31]);
-	MONT_MAC(v0, v1, v2, u[3], m[30]);
-	MONT_MAC(w0, w1, w2, u[4], m[29]);
-	MONT_MAC(t0, t1, t2, u[5], m[28]);
-	MONT_MAC(v0, v1, v2, u[6], m[27]);
-	MONT_MAC(w0, w1, w2, u[7], m[26]);
-	MONT_MAC(t0, t1, t2, u[8], m[25]);
-	MONT_MAC(v0, v1, v2, u[9], m[24]);
-	MONT_MAC(w0, w1, w2, u[10], m[23]);
-	MONT_MAC(t0, t1, t2, u[11], m[22]);
-	MONT_MAC(v0, v1, v2, u[12], m[21]);
-	MONT_MAC(w0, w1, w2, u[13], m[20]);
-	MONT_MAC(t0, t1, t2, u[14], m[19]);
-	MONT_MAC(v0, v1, v2, u[15], m[18]);
-	MONT_MAC(w0, w1, w2, u[16], m[17]);
-	MONT_MAC(t0, t1, t2, u[17], m[16]);
-	MONT_MAC(v0, v1, v2, u[18], m[15]);
-	MONT_MAC(w0, w1, w2, u[19], m[14]);
-	MONT_MAC(t0, t1, t2, u[20], m[13]);
-	MONT_MAC(v0, v1, v2, u[21], m[12]);
-	MONT_MAC(w0, w1, w2, u[22], m[11]);
-	MONT_MAC(t0, t1, t2, u[23], m[10]);
-	MONT_MAC(v0, v1, v2, u[24], m[9]);
-	MONT_MAC(w0, w1, w2, u[25], m[8]);
-	MONT_MAC(t0, t1, t2, u[26], m[7]);
-	MONT_MAC(v0, v1, v2, u[27], m[6]);
-	MONT_MAC(w0, w1, w2, u[28], m[5]);
-	MONT_MAC(t0, t1, t2, u[29], m[4]);
-	MONT_MAC(v0, v1, v2, u[30], m[3]);
-	MONT_MAC(w0, w1, w2, u[31], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 34 */
-	MONT_MAC(t0, t1, t2, a[3], b[31]);
-	MONT_MUL(v0, v1, v2, a[4], b[30]);
-	MONT_MUL(w0, w1, w2, a[5], b[29]);
-	MONT_MAC(t0, t1, t2, a[6], b[28]);
-	MONT_MAC(v0, v1, v2, a[7], b[27]);
-	MONT_MAC(w0, w1, w2, a[8], b[26]);
-	MONT_MAC(t0, t1, t2, a[9], b[25]);
-	MONT_MAC(v0, v1, v2, a[10], b[24]);
-	MONT_MAC(w0, w1, w2, a[11], b[23]);
-	MONT_MAC(t0, t1, t2, a[12], b[22]);
-	MONT_MAC(v0, v1, v2, a[13], b[21]);
-	MONT_MAC(w0, w1, w2, a[14], b[20]);
-	MONT_MAC(t0, t1, t2, a[15], b[19]);
-	MONT_MAC(v0, v1, v2, a[16], b[18]);
-	MONT_MAC(w0, w1, w2, a[17], b[17]);
-	MONT_MAC(t0, t1, t2, a[18], b[16]);
-	MONT_MAC(v0, v1, v2, a[19], b[15]);
-	MONT_MAC(w0, w1, w2, a[20], b[14]);
-	MONT_MAC(t0, t1, t2, a[21], b[13]);
-	MONT_MAC(v0, v1, v2, a[22], b[12]);
-	MONT_MAC(w0, w1, w2, a[23], b[11]);
-	MONT_MAC(t0, t1, t2, a[24], b[10]);
-	MONT_MAC(v0, v1, v2, a[25], b[9]);
-	MONT_MAC(w0, w1, w2, a[26], b[8]);
-	MONT_MAC(t0, t1, t2, a[27], b[7]);
-	MONT_MAC(v0, v1, v2, a[28], b[6]);
-	MONT_MAC(w0, w1, w2, a[29], b[5]);
-	MONT_MAC(t0, t1, t2, a[30], b[4]);
-	MONT_MAC(v0, v1, v2, a[31], b[3]);
-	MONT_MAC(w0, w1, w2, u[3], m[31]);
-	MONT_MAC(t0, t1, t2, u[4], m[30]);
-	MONT_MAC(v0, v1, v2, u[5], m[29]);
-	MONT_MAC(w0, w1, w2, u[6], m[28]);
-	MONT_MAC(t0, t1, t2, u[7], m[27]);
-	MONT_MAC(v0, v1, v2, u[8], m[26]);
-	MONT_MAC(w0, w1, w2, u[9], m[25]);
-	MONT_MAC(t0, t1, t2, u[10], m[24]);
-	MONT_MAC(v0, v1, v2, u[11], m[23]);
-	MONT_MAC(w0, w1, w2, u[12], m[22]);
-	MONT_MAC(t0, t1, t2, u[13], m[21]);
-	MONT_MAC(v0, v1, v2, u[14], m[20]);
-	MONT_MAC(w0, w1, w2, u[15], m[19]);
-	MONT_MAC(t0, t1, t2, u[16], m[18]);
-	MONT_MAC(v0, v1, v2, u[17], m[17]);
-	MONT_MAC(w0, w1, w2, u[18], m[16]);
-	MONT_MAC(t0, t1, t2, u[19], m[15]);
-	MONT_MAC(v0, v1, v2, u[20], m[14]);
-	MONT_MAC(w0, w1, w2, u[21], m[13]);
-	MONT_MAC(t0, t1, t2, u[22], m[12]);
-	MONT_MAC(v0, v1, v2, u[23], m[11]);
-	MONT_MAC(w0, w1, w2, u[24], m[10]);
-	MONT_MAC(t0, t1, t2, u[25], m[9]);
-	MONT_MAC(v0, v1, v2, u[26], m[8]);
-	MONT_MAC(w0, w1, w2, u[27], m[7]);
-	MONT_MAC(t0, t1, t2, u[28], m[6]);
-	MONT_MAC(v0, v1, v2, u[29], m[5]);
-	MONT_MAC(w0, w1, w2, u[30], m[4]);
-	MONT_MAC(t0, t1, t2, u[31], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 35 */
-	MONT_MAC(t0, t1, t2, a[4], b[31]);
-	MONT_MUL(v0, v1, v2, a[5], b[30]);
-	MONT_MUL(w0, w1, w2, a[6], b[29]);
-	MONT_MAC(t0, t1, t2, a[7], b[28]);
-	MONT_MAC(v0, v1, v2, a[8], b[27]);
-	MONT_MAC(w0, w1, w2, a[9], b[26]);
-	MONT_MAC(t0, t1, t2, a[10], b[25]);
-	MONT_MAC(v0, v1, v2, a[11], b[24]);
-	MONT_MAC(w0, w1, w2, a[12], b[23]);
-	MONT_MAC(t0, t1, t2, a[13], b[22]);
-	MONT_MAC(v0, v1, v2, a[14], b[21]);
-	MONT_MAC(w0, w1, w2, a[15], b[20]);
-	MONT_MAC(t0, t1, t2, a[16], b[19]);
-	MONT_MAC(v0, v1, v2, a[17], b[18]);
-	MONT_MAC(w0, w1, w2, a[18], b[17]);
-	MONT_MAC(t0, t1, t2, a[19], b[16]);
-	MONT_MAC(v0, v1, v2, a[20], b[15]);
-	MONT_MAC(w0, w1, w2, a[21], b[14]);
-	MONT_MAC(t0, t1, t2, a[22], b[13]);
-	MONT_MAC(v0, v1, v2, a[23], b[12]);
-	MONT_MAC(w0, w1, w2, a[24], b[11]);
-	MONT_MAC(t0, t1, t2, a[25], b[10]);
-	MONT_MAC(v0, v1, v2, a[26], b[9]);
-	MONT_MAC(w0, w1, w2, a[27], b[8]);
-	MONT_MAC(t0, t1, t2, a[28], b[7]);
-	MONT_MAC(v0, v1, v2, a[29], b[6]);
-	MONT_MAC(w0, w1, w2, a[30], b[5]);
-	MONT_MAC(t0, t1, t2, a[31], b[4]);
-	MONT_MAC(v0, v1, v2, u[4], m[31]);
-	MONT_MAC(w0, w1, w2, u[5], m[30]);
-	MONT_MAC(t0, t1, t2, u[6], m[29]);
-	MONT_MAC(v0, v1, v2, u[7], m[28]);
-	MONT_MAC(w0, w1, w2, u[8], m[27]);
-	MONT_MAC(t0, t1, t2, u[9], m[26]);
-	MONT_MAC(v0, v1, v2, u[10], m[25]);
-	MONT_MAC(w0, w1, w2, u[11], m[24]);
-	MONT_MAC(t0, t1, t2, u[12], m[23]);
-	MONT_MAC(v0, v1, v2, u[13], m[22]);
-	MONT_MAC(w0, w1, w2, u[14], m[21]);
-	MONT_MAC(t0, t1, t2, u[15], m[20]);
-	MONT_MAC(v0, v1, v2, u[16], m[19]);
-	MONT_MAC(w0, w1, w2, u[17], m[18]);
-	MONT_MAC(t0, t1, t2, u[18], m[17]);
-	MONT_MAC(v0, v1, v2, u[19], m[16]);
-	MONT_MAC(w0, w1, w2, u[20], m[15]);
-	MONT_MAC(t0, t1, t2, u[21], m[14]);
-	MONT_MAC(v0, v1, v2, u[22], m[13]);
-	MONT_MAC(w0, w1, w2, u[23], m[12]);
-	MONT_MAC(t0, t1, t2, u[24], m[11]);
-	MONT_MAC(v0, v1, v2, u[25], m[10]);
-	MONT_MAC(w0, w1, w2, u[26], m[9]);
-	MONT_MAC(t0, t1, t2, u[27], m[8]);
-	MONT_MAC(v0, v1, v2, u[28], m[7]);
-	MONT_MAC(w0, w1, w2, u[29], m[6]);
-	MONT_MAC(t0, t1, t2, u[30], m[5]);
-	MONT_MAC(v0, v1, v2, u[31], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 36 */
-	MONT_MAC(t0, t1, t2, a[5], b[31]);
-	MONT_MUL(v0, v1, v2, a[6], b[30]);
-	MONT_MUL(w0, w1, w2, a[7], b[29]);
-	MONT_MAC(t0, t1, t2, a[8], b[28]);
-	MONT_MAC(v0, v1, v2, a[9], b[27]);
-	MONT_MAC(w0, w1, w2, a[10], b[26]);
-	MONT_MAC(t0, t1, t2, a[11], b[25]);
-	MONT_MAC(v0, v1, v2, a[12], b[24]);
-	MONT_MAC(w0, w1, w2, a[13], b[23]);
-	MONT_MAC(t0, t1, t2, a[14], b[22]);
-	MONT_MAC(v0, v1, v2, a[15], b[21]);
-	MONT_MAC(w0, w1, w2, a[16], b[20]);
-	MONT_MAC(t0, t1, t2, a[17], b[19]);
-	MONT_MAC(v0, v1, v2, a[18], b[18]);
-	MONT_MAC(w0, w1, w2, a[19], b[17]);
-	MONT_MAC(t0, t1, t2, a[20], b[16]);
-	MONT_MAC(v0, v1, v2, a[21], b[15]);
-	MONT_MAC(w0, w1, w2, a[22], b[14]);
-	MONT_MAC(t0, t1, t2, a[23], b[13]);
-	MONT_MAC(v0, v1, v2, a[24], b[12]);
-	MONT_MAC(w0, w1, w2, a[25], b[11]);
-	MONT_MAC(t0, t1, t2, a[26], b[10]);
-	MONT_MAC(v0, v1, v2, a[27], b[9]);
-	MONT_MAC(w0, w1, w2, a[28], b[8]);
-	MONT_MAC(t0, t1, t2, a[29], b[7]);
-	MONT_MAC(v0, v1, v2, a[30], b[6]);
-	MONT_MAC(w0, w1, w2, a[31], b[5]);
-	MONT_MAC(t0, t1, t2, u[5], m[31]);
-	MONT_MAC(v0, v1, v2, u[6], m[30]);
-	MONT_MAC(w0, w1, w2, u[7], m[29]);
-	MONT_MAC(t0, t1, t2, u[8], m[28]);
-	MONT_MAC(v0, v1, v2, u[9], m[27]);
-	MONT_MAC(w0, w1, w2, u[10], m[26]);
-	MONT_MAC(t0, t1, t2, u[11], m[25]);
-	MONT_MAC(v0, v1, v2, u[12], m[24]);
-	MONT_MAC(w0, w1, w2, u[13], m[23]);
-	MONT_MAC(t0, t1, t2, u[14], m[22]);
-	MONT_MAC(v0, v1, v2, u[15], m[21]);
-	MONT_MAC(w0, w1, w2, u[16], m[20]);
-	MONT_MAC(t0, t1, t2, u[17], m[19]);
-	MONT_MAC(v0, v1, v2, u[18], m[18]);
-	MONT_MAC(w0, w1, w2, u[19], m[17]);
-	MONT_MAC(t0, t1, t2, u[20], m[16]);
-	MONT_MAC(v0, v1, v2, u[21], m[15]);
-	MONT_MAC(w0, w1, w2, u[22], m[14]);
-	MONT_MAC(t0, t1, t2, u[23], m[13]);
-	MONT_MAC(v0, v1, v2, u[24], m[12]);
-	MONT_MAC(w0, w1, w2, u[25], m[11]);
-	MONT_MAC(t0, t1, t2, u[26], m[10]);
-	MONT_MAC(v0, v1, v2, u[27], m[9]);
-	MONT_MAC(w0, w1, w2, u[28], m[8]);
-	MONT_MAC(t0, t1, t2, u[29], m[7]);
-	MONT_MAC(v0, v1, v2, u[30], m[6]);
-	MONT_MAC(w0, w1, w2, u[31], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 37 */
-	MONT_MAC(t0, t1, t2, a[6], b[31]);
-	MONT_MUL(v0, v1, v2, a[7], b[30]);
-	MONT_MUL(w0, w1, w2, a[8], b[29]);
-	MONT_MAC(t0, t1, t2, a[9], b[28]);
-	MONT_MAC(v0, v1, v2, a[10], b[27]);
-	MONT_MAC(w0, w1, w2, a[11], b[26]);
-	MONT_MAC(t0, t1, t2, a[12], b[25]);
-	MONT_MAC(v0, v1, v2, a[13], b[24]);
-	MONT_MAC(w0, w1, w2, a[14], b[23]);
-	MONT_MAC(t0, t1, t2, a[15], b[22]);
-	MONT_MAC(v0, v1, v2, a[16], b[21]);
-	MONT_MAC(w0, w1, w2, a[17], b[20]);
-	MONT_MAC(t0, t1, t2, a[18], b[19]);
-	MONT_MAC(v0, v1, v2, a[19], b[18]);
-	MONT_MAC(w0, w1, w2, a[20], b[17]);
-	MONT_MAC(t0, t1, t2, a[21], b[16]);
-	MONT_MAC(v0, v1, v2, a[22], b[15]);
-	MONT_MAC(w0, w1, w2, a[23], b[14]);
-	MONT_MAC(t0, t1, t2, a[24], b[13]);
-	MONT_MAC(v0, v1, v2, a[25], b[12]);
-	MONT_MAC(w0, w1, w2, a[26], b[11]);
-	MONT_MAC(t0, t1, t2, a[27], b[10]);
-	MONT_MAC(v0, v1, v2, a[28], b[9]);
-	MONT_MAC(w0, w1, w2, a[29], b[8]);
-	MONT_MAC(t0, t1, t2, a[30], b[7]);
-	MONT_MAC(v0, v1, v2, a[31], b[6]);
-	MONT_MAC(w0, w1, w2, u[6], m[31]);
-	MONT_MAC(t0, t1, t2, u[7], m[30]);
-	MONT_MAC(v0, v1, v2, u[8], m[29]);
-	MONT_MAC(w0, w1, w2, u[9], m[28]);
-	MONT_MAC(t0, t1, t2, u[10], m[27]);
-	MONT_MAC(v0, v1, v2, u[11], m[26]);
-	MONT_MAC(w0, w1, w2, u[12], m[25]);
-	MONT_MAC(t0, t1, t2, u[13], m[24]);
-	MONT_MAC(v0, v1, v2, u[14], m[23]);
-	MONT_MAC(w0, w1, w2, u[15], m[22]);
-	MONT_MAC(t0, t1, t2, u[16], m[21]);
-	MONT_MAC(v0, v1, v2, u[17], m[20]);
-	MONT_MAC(w0, w1, w2, u[18], m[19]);
-	MONT_MAC(t0, t1, t2, u[19], m[18]);
-	MONT_MAC(v0, v1, v2, u[20], m[17]);
-	MONT_MAC(w0, w1, w2, u[21], m[16]);
-	MONT_MAC(t0, t1, t2, u[22], m[15]);
-	MONT_MAC(v0, v1, v2, u[23], m[14]);
-	MONT_MAC(w0, w1, w2, u[24], m[13]);
-	MONT_MAC(t0, t1, t2, u[25], m[12]);
-	MONT_MAC(v0, v1, v2, u[26], m[11]);
-	MONT_MAC(w0, w1, w2, u[27], m[10]);
-	MONT_MAC(t0, t1, t2, u[28], m[9]);
-	MONT_MAC(v0, v1, v2, u[29], m[8]);
-	MONT_MAC(w0, w1, w2, u[30], m[7]);
-	MONT_MAC(t0, t1, t2, u[31], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 38 */
-	MONT_MAC(t0, t1, t2, a[7], b[31]);
-	MONT_MUL(v0, v1, v2, a[8], b[30]);
-	MONT_MUL(w0, w1, w2, a[9], b[29]);
-	MONT_MAC(t0, t1, t2, a[10], b[28]);
-	MONT_MAC(v0, v1, v2, a[11], b[27]);
-	MONT_MAC(w0, w1, w2, a[12], b[26]);
-	MONT_MAC(t0, t1, t2, a[13], b[25]);
-	MONT_MAC(v0, v1, v2, a[14], b[24]);
-	MONT_MAC(w0, w1, w2, a[15], b[23]);
-	MONT_MAC(t0, t1, t2, a[16], b[22]);
-	MONT_MAC(v0, v1, v2, a[17], b[21]);
-	MONT_MAC(w0, w1, w2, a[18], b[20]);
-	MONT_MAC(t0, t1, t2, a[19], b[19]);
-	MONT_MAC(v0, v1, v2, a[20], b[18]);
-	MONT_MAC(w0, w1, w2, a[21], b[17]);
-	MONT_MAC(t0, t1, t2, a[22], b[16]);
-	MONT_MAC(v0, v1, v2, a[23], b[15]);
-	MONT_MAC(w0, w1, w2, a[24], b[14]);
-	MONT_MAC(t0, t1, t2, a[25], b[13]);
-	MONT_MAC(v0, v1, v2, a[26], b[12]);
-	MONT_MAC(w0, w1, w2, a[27], b[11]);
-	MONT_MAC(t0, t1, t2, a[28], b[10]);
-	MONT_MAC(v0, v1, v2, a[29], b[9]);
-	MONT_MAC(w0, w1, w2, a[30], b[8]);
-	MONT_MAC(t0, t1, t2, a[31], b[7]);
-	MONT_MAC(v0, v1, v2, u[7], m[31]);
-	MONT_MAC(w0, w1, w2, u[8], m[30]);
-	MONT_MAC(t0, t1, t2, u[9], m[29]);
-	MONT_MAC(v0, v1, v2, u[10], m[28]);
-	MONT_MAC(w0, w1, w2, u[11], m[27]);
-	MONT_MAC(t0, t1, t2, u[12], m[26]);
-	MONT_MAC(v0, v1, v2, u[13], m[25]);
-	MONT_MAC(w0, w1, w2, u[14], m[24]);
-	MONT_MAC(t0, t1, t2, u[15], m[23]);
-	MONT_MAC(v0, v1, v2, u[16], m[22]);
-	MONT_MAC(w0, w1, w2, u[17], m[21]);
-	MONT_MAC(t0, t1, t2, u[18], m[20]);
-	MONT_MAC(v0, v1, v2, u[19], m[19]);
-	MONT_MAC(w0, w1, w2, u[20], m[18]);
-	MONT_MAC(t0, t1, t2, u[21], m[17]);
-	MONT_MAC(v0, v1, v2, u[22], m[16]);
-	MONT_MAC(w0, w1, w2, u[23], m[15]);
-	MONT_MAC(t0, t1, t2, u[24], m[14]);
-	MONT_MAC(v0, v1, v2, u[25], m[13]);
-	MONT_MAC(w0, w1, w2, u[26], m[12]);
-	MONT_MAC(t0, t1, t2, u[27], m[11]);
-	MONT_MAC(v0, v1, v2, u[28], m[10]);
-	MONT_MAC(w0, w1, w2, u[29], m[9]);
-	MONT_MAC(t0, t1, t2, u[30], m[8]);
-	MONT_MAC(v0, v1, v2, u[31], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 39 */
-	MONT_MAC(t0, t1, t2, a[8], b[31]);
-	MONT_MUL(v0, v1, v2, a[9], b[30]);
-	MONT_MUL(w0, w1, w2, a[10], b[29]);
-	MONT_MAC(t0, t1, t2, a[11], b[28]);
-	MONT_MAC(v0, v1, v2, a[12], b[27]);
-	MONT_MAC(w0, w1, w2, a[13], b[26]);
-	MONT_MAC(t0, t1, t2, a[14], b[25]);
-	MONT_MAC(v0, v1, v2, a[15], b[24]);
-	MONT_MAC(w0, w1, w2, a[16], b[23]);
-	MONT_MAC(t0, t1, t2, a[17], b[22]);
-	MONT_MAC(v0, v1, v2, a[18], b[21]);
-	MONT_MAC(w0, w1, w2, a[19], b[20]);
-	MONT_MAC(t0, t1, t2, a[20], b[19]);
-	MONT_MAC(v0, v1, v2, a[21], b[18]);
-	MONT_MAC(w0, w1, w2, a[22], b[17]);
-	MONT_MAC(t0, t1, t2, a[23], b[16]);
-	MONT_MAC(v0, v1, v2, a[24], b[15]);
-	MONT_MAC(w0, w1, w2, a[25], b[14]);
-	MONT_MAC(t0, t1, t2, a[26], b[13]);
-	MONT_MAC(v0, v1, v2, a[27], b[12]);
-	MONT_MAC(w0, w1, w2, a[28], b[11]);
-	MONT_MAC(t0, t1, t2, a[29], b[10]);
-	MONT_MAC(v0, v1, v2, a[30], b[9]);
-	MONT_MAC(w0, w1, w2, a[31], b[8]);
-	MONT_MAC(t0, t1, t2, u[8], m[31]);
-	MONT_MAC(v0, v1, v2, u[9], m[30]);
-	MONT_MAC(w0, w1, w2, u[10], m[29]);
-	MONT_MAC(t0, t1, t2, u[11], m[28]);
-	MONT_MAC(v0, v1, v2, u[12], m[27]);
-	MONT_MAC(w0, w1, w2, u[13], m[26]);
-	MONT_MAC(t0, t1, t2, u[14], m[25]);
-	MONT_MAC(v0, v1, v2, u[15], m[24]);
-	MONT_MAC(w0, w1, w2, u[16], m[23]);
-	MONT_MAC(t0, t1, t2, u[17], m[22]);
-	MONT_MAC(v0, v1, v2, u[18], m[21]);
-	MONT_MAC(w0, w1, w2, u[19], m[20]);
-	MONT_MAC(t0, t1, t2, u[20], m[19]);
-	MONT_MAC(v0, v1, v2, u[21], m[18]);
-	MONT_MAC(w0, w1, w2, u[22], m[17]);
-	MONT_MAC(t0, t1, t2, u[23], m[16]);
-	MONT_MAC(v0, v1, v2, u[24], m[15]);
-	MONT_MAC(w0, w1, w2, u[25], m[14]);
-	MONT_MAC(t0, t1, t2, u[26], m[13]);
-	MONT_MAC(v0, v1, v2, u[27], m[12]);
-	MONT_MAC(w0, w1, w2, u[28], m[11]);
-	MONT_MAC(t0, t1, t2, u[29], m[10]);
-	MONT_MAC(v0, v1, v2, u[30], m[9]);
-	MONT_MAC(w0, w1, w2, u[31], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 40 */
-	MONT_MAC(t0, t1, t2, a[9], b[31]);
-	MONT_MUL(v0, v1, v2, a[10], b[30]);
-	MONT_MUL(w0, w1, w2, a[11], b[29]);
-	MONT_MAC(t0, t1, t2, a[12], b[28]);
-	MONT_MAC(v0, v1, v2, a[13], b[27]);
-	MONT_MAC(w0, w1, w2, a[14], b[26]);
-	MONT_MAC(t0, t1, t2, a[15], b[25]);
-	MONT_MAC(v0, v1, v2, a[16], b[24]);
-	MONT_MAC(w0, w1, w2, a[17], b[23]);
-	MONT_MAC(t0, t1, t2, a[18], b[22]);
-	MONT_MAC(v0, v1, v2, a[19], b[21]);
-	MONT_MAC(w0, w1, w2, a[20], b[20]);
-	MONT_MAC(t0, t1, t2, a[21], b[19]);
-	MONT_MAC(v0, v1, v2, a[22], b[18]);
-	MONT_MAC(w0, w1, w2, a[23], b[17]);
-	MONT_MAC(t0, t1, t2, a[24], b[16]);
-	MONT_MAC(v0, v1, v2, a[25], b[15]);
-	MONT_MAC(w0, w1, w2, a[26], b[14]);
-	MONT_MAC(t0, t1, t2, a[27], b[13]);
-	MONT_MAC(v0, v1, v2, a[28], b[12]);
-	MONT_MAC(w0, w1, w2, a[29], b[11]);
-	MONT_MAC(t0, t1, t2, a[30], b[10]);
-	MONT_MAC(v0, v1, v2, a[31], b[9]);
-	MONT_MAC(w0, w1, w2, u[9], m[31]);
-	MONT_MAC(t0, t1, t2, u[10], m[30]);
-	MONT_MAC(v0, v1, v2, u[11], m[29]);
-	MONT_MAC(w0, w1, w2, u[12], m[28]);
-	MONT_MAC(t0, t1, t2, u[13], m[27]);
-	MONT_MAC(v0, v1, v2, u[14], m[26]);
-	MONT_MAC(w0, w1, w2, u[15], m[25]);
-	MONT_MAC(t0, t1, t2, u[16], m[24]);
-	MONT_MAC(v0, v1, v2, u[17], m[23]);
-	MONT_MAC(w0, w1, w2, u[18], m[22]);
-	MONT_MAC(t0, t1, t2, u[19], m[21]);
-	MONT_MAC(v0, v1, v2, u[20], m[20]);
-	MONT_MAC(w0, w1, w2, u[21], m[19]);
-	MONT_MAC(t0, t1, t2, u[22], m[18]);
-	MONT_MAC(v0, v1, v2, u[23], m[17]);
-	MONT_MAC(w0, w1, w2, u[24], m[16]);
-	MONT_MAC(t0, t1, t2, u[25], m[15]);
-	MONT_MAC(v0, v1, v2, u[26], m[14]);
-	MONT_MAC(w0, w1, w2, u[27], m[13]);
-	MONT_MAC(t0, t1, t2, u[28], m[12]);
-	MONT_MAC(v0, v1, v2, u[29], m[11]);
-	MONT_MAC(w0, w1, w2, u[30], m[10]);
-	MONT_MAC(t0, t1, t2, u[31], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 41 */
-	MONT_MAC(t0, t1, t2, a[10], b[31]);
-	MONT_MUL(v0, v1, v2, a[11], b[30]);
-	MONT_MUL(w0, w1, w2, a[12], b[29]);
-	MONT_MAC(t0, t1, t2, a[13], b[28]);
-	MONT_MAC(v0, v1, v2, a[14], b[27]);
-	MONT_MAC(w0, w1, w2, a[15], b[26]);
-	MONT_MAC(t0, t1, t2, a[16], b[25]);
-	MONT_MAC(v0, v1, v2, a[17], b[24]);
-	MONT_MAC(w0, w1, w2, a[18], b[23]);
-	MONT_MAC(t0, t1, t2, a[19], b[22]);
-	MONT_MAC(v0, v1, v2, a[20], b[21]);
-	MONT_MAC(w0, w1, w2, a[21], b[20]);
-	MONT_MAC(t0, t1, t2, a[22], b[19]);
-	MONT_MAC(v0, v1, v2, a[23], b[18]);
-	MONT_MAC(w0, w1, w2, a[24], b[17]);
-	MONT_MAC(t0, t1, t2, a[25], b[16]);
-	MONT_MAC(v0, v1, v2, a[26], b[15]);
-	MONT_MAC(w0, w1, w2, a[27], b[14]);
-	MONT_MAC(t0, t1, t2, a[28], b[13]);
-	MONT_MAC(v0, v1, v2, a[29], b[12]);
-	MONT_MAC(w0, w1, w2, a[30], b[11]);
-	MONT_MAC(t0, t1, t2, a[31], b[10]);
-	MONT_MAC(v0, v1, v2, u[10], m[31]);
-	MONT_MAC(w0, w1, w2, u[11], m[30]);
-	MONT_MAC(t0, t1, t2, u[12], m[29]);
-	MONT_MAC(v0, v1, v2, u[13], m[28]);
-	MONT_MAC(w0, w1, w2, u[14], m[27]);
-	MONT_MAC(t0, t1, t2, u[15], m[26]);
-	MONT_MAC(v0, v1, v2, u[16], m[25]);
-	MONT_MAC(w0, w1, w2, u[17], m[24]);
-	MONT_MAC(t0, t1, t2, u[18], m[23]);
-	MONT_MAC(v0, v1, v2, u[19], m[22]);
-	MONT_MAC(w0, w1, w2, u[20], m[21]);
-	MONT_MAC(t0, t1, t2, u[21], m[20]);
-	MONT_MAC(v0, v1, v2, u[22], m[19]);
-	MONT_MAC(w0, w1, w2, u[23], m[18]);
-	MONT_MAC(t0, t1, t2, u[24], m[17]);
-	MONT_MAC(v0, v1, v2, u[25], m[16]);
-	MONT_MAC(w0, w1, w2, u[26], m[15]);
-	MONT_MAC(t0, t1, t2, u[27], m[14]);
-	MONT_MAC(v0, v1, v2, u[28], m[13]);
-	MONT_MAC(w0, w1, w2, u[29], m[12]);
-	MONT_MAC(t0, t1, t2, u[30], m[11]);
-	MONT_MAC(v0, v1, v2, u[31], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 42 */
-	MONT_MAC(t0, t1, t2, a[11], b[31]);
-	MONT_MUL(v0, v1, v2, a[12], b[30]);
-	MONT_MUL(w0, w1, w2, a[13], b[29]);
-	MONT_MAC(t0, t1, t2, a[14], b[28]);
-	MONT_MAC(v0, v1, v2, a[15], b[27]);
-	MONT_MAC(w0, w1, w2, a[16], b[26]);
-	MONT_MAC(t0, t1, t2, a[17], b[25]);
-	MONT_MAC(v0, v1, v2, a[18], b[24]);
-	MONT_MAC(w0, w1, w2, a[19], b[23]);
-	MONT_MAC(t0, t1, t2, a[20], b[22]);
-	MONT_MAC(v0, v1, v2, a[21], b[21]);
-	MONT_MAC(w0, w1, w2, a[22], b[20]);
-	MONT_MAC(t0, t1, t2, a[23], b[19]);
-	MONT_MAC(v0, v1, v2, a[24], b[18]);
-	MONT_MAC(w0, w1, w2, a[25], b[17]);
-	MONT_MAC(t0, t1, t2, a[26], b[16]);
-	MONT_MAC(v0, v1, v2, a[27], b[15]);
-	MONT_MAC(w0, w1, w2, a[28], b[14]);
-	MONT_MAC(t0, t1, t2, a[29], b[13]);
-	MONT_MAC(v0, v1, v2, a[30], b[12]);
-	MONT_MAC(w0, w1, w2, a[31], b[11]);
-	MONT_MAC(t0, t1, t2, u[11], m[31]);
-	MONT_MAC(v0, v1, v2, u[12], m[30]);
-	MONT_MAC(w0, w1, w2, u[13], m[29]);
-	MONT_MAC(t0, t1, t2, u[14], m[28]);
-	MONT_MAC(v0, v1, v2, u[15], m[27]);
-	MONT_MAC(w0, w1, w2, u[16], m[26]);
-	MONT_MAC(t0, t1, t2, u[17], m[25]);
-	MONT_MAC(v0, v1, v2, u[18], m[24]);
-	MONT_MAC(w0, w1, w2, u[19], m[23]);
-	MONT_MAC(t0, t1, t2, u[20], m[22]);
-	MONT_MAC(v0, v1, v2, u[21], m[21]);
-	MONT_MAC(w0, w1, w2, u[22], m[20]);
-	MONT_MAC(t0, t1, t2, u[23], m[19]);
-	MONT_MAC(v0, v1, v2, u[24], m[18]);
-	MONT_MAC(w0, w1, w2, u[25], m[17]);
-	MONT_MAC(t0, t1, t2, u[26], m[16]);
-	MONT_MAC(v0, v1, v2, u[27], m[15]);
-	MONT_MAC(w0, w1, w2, u[28], m[14]);
-	MONT_MAC(t0, t1, t2, u[29], m[13]);
-	MONT_MAC(v0, v1, v2, u[30], m[12]);
-	MONT_MAC(w0, w1, w2, u[31], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 43 */
-	MONT_MAC(t0, t1, t2, a[12], b[31]);
-	MONT_MUL(v0, v1, v2, a[13], b[30]);
-	MONT_MUL(w0, w1, w2, a[14], b[29]);
-	MONT_MAC(t0, t1, t2, a[15], b[28]);
-	MONT_MAC(v0, v1, v2, a[16], b[27]);
-	MONT_MAC(w0, w1, w2, a[17], b[26]);
-	MONT_MAC(t0, t1, t2, a[18], b[25]);
-	MONT_MAC(v0, v1, v2, a[19], b[24]);
-	MONT_MAC(w0, w1, w2, a[20], b[23]);
-	MONT_MAC(t0, t1, t2, a[21], b[22]);
-	MONT_MAC(v0, v1, v2, a[22], b[21]);
-	MONT_MAC(w0, w1, w2, a[23], b[20]);
-	MONT_MAC(t0, t1, t2, a[24], b[19]);
-	MONT_MAC(v0, v1, v2, a[25], b[18]);
-	MONT_MAC(w0, w1, w2, a[26], b[17]);
-	MONT_MAC(t0, t1, t2, a[27], b[16]);
-	MONT_MAC(v0, v1, v2, a[28], b[15]);
-	MONT_MAC(w0, w1, w2, a[29], b[14]);
-	MONT_MAC(t0, t1, t2, a[30], b[13]);
-	MONT_MAC(v0, v1, v2, a[31], b[12]);
-	MONT_MAC(w0, w1, w2, u[12], m[31]);
-	MONT_MAC(t0, t1, t2, u[13], m[30]);
-	MONT_MAC(v0, v1, v2, u[14], m[29]);
-	MONT_MAC(w0, w1, w2, u[15], m[28]);
-	MONT_MAC(t0, t1, t2, u[16], m[27]);
-	MONT_MAC(v0, v1, v2, u[17], m[26]);
-	MONT_MAC(w0, w1, w2, u[18], m[25]);
-	MONT_MAC(t0, t1, t2, u[19], m[24]);
-	MONT_MAC(v0, v1, v2, u[20], m[23]);
-	MONT_MAC(w0, w1, w2, u[21], m[22]);
-	MONT_MAC(t0, t1, t2, u[22], m[21]);
-	MONT_MAC(v0, v1, v2, u[23], m[20]);
-	MONT_MAC(w0, w1, w2, u[24], m[19]);
-	MONT_MAC(t0, t1, t2, u[25], m[18]);
-	MONT_MAC(v0, v1, v2, u[26], m[17]);
-	MONT_MAC(w0, w1, w2, u[27], m[16]);
-	MONT_MAC(t0, t1, t2, u[28], m[15]);
-	MONT_MAC(v0, v1, v2, u[29], m[14]);
-	MONT_MAC(w0, w1, w2, u[30], m[13]);
-	MONT_MAC(t0, t1, t2, u[31], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 44 */
-	MONT_MAC(t0, t1, t2, a[13], b[31]);
-	MONT_MUL(v0, v1, v2, a[14], b[30]);
-	MONT_MUL(w0, w1, w2, a[15], b[29]);
-	MONT_MAC(t0, t1, t2, a[16], b[28]);
-	MONT_MAC(v0, v1, v2, a[17], b[27]);
-	MONT_MAC(w0, w1, w2, a[18], b[26]);
-	MONT_MAC(t0, t1, t2, a[19], b[25]);
-	MONT_MAC(v0, v1, v2, a[20], b[24]);
-	MONT_MAC(w0, w1, w2, a[21], b[23]);
-	MONT_MAC(t0, t1, t2, a[22], b[22]);
-	MONT_MAC(v0, v1, v2, a[23], b[21]);
-	MONT_MAC(w0, w1, w2, a[24], b[20]);
-	MONT_MAC(t0, t1, t2, a[25], b[19]);
-	MONT_MAC(v0, v1, v2, a[26], b[18]);
-	MONT_MAC(w0, w1, w2, a[27], b[17]);
-	MONT_MAC(t0, t1, t2, a[28], b[16]);
-	MONT_MAC(v0, v1, v2, a[29], b[15]);
-	MONT_MAC(w0, w1, w2, a[30], b[14]);
-	MONT_MAC(t0, t1, t2, a[31], b[13]);
-	MONT_MAC(v0, v1, v2, u[13], m[31]);
-	MONT_MAC(w0, w1, w2, u[14], m[30]);
-	MONT_MAC(t0, t1, t2, u[15], m[29]);
-	MONT_MAC(v0, v1, v2, u[16], m[28]);
-	MONT_MAC(w0, w1, w2, u[17], m[27]);
-	MONT_MAC(t0, t1, t2, u[18], m[26]);
-	MONT_MAC(v0, v1, v2, u[19], m[25]);
-	MONT_MAC(w0, w1, w2, u[20], m[24]);
-	MONT_MAC(t0, t1, t2, u[21], m[23]);
-	MONT_MAC(v0, v1, v2, u[22], m[22]);
-	MONT_MAC(w0, w1, w2, u[23], m[21]);
-	MONT_MAC(t0, t1, t2, u[24], m[20]);
-	MONT_MAC(v0, v1, v2, u[25], m[19]);
-	MONT_MAC(w0, w1, w2, u[26], m[18]);
-	MONT_MAC(t0, t1, t2, u[27], m[17]);
-	MONT_MAC(v0, v1, v2, u[28], m[16]);
-	MONT_MAC(w0, w1, w2, u[29], m[15]);
-	MONT_MAC(t0, t1, t2, u[30], m[14]);
-	MONT_MAC(v0, v1, v2, u[31], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 45 */
-	MONT_MAC(t0, t1, t2, a[14], b[31]);
-	MONT_MUL(v0, v1, v2, a[15], b[30]);
-	MONT_MUL(w0, w1, w2, a[16], b[29]);
-	MONT_MAC(t0, t1, t2, a[17], b[28]);
-	MONT_MAC(v0, v1, v2, a[18], b[27]);
-	MONT_MAC(w0, w1, w2, a[19], b[26]);
-	MONT_MAC(t0, t1, t2, a[20], b[25]);
-	MONT_MAC(v0, v1, v2, a[21], b[24]);
-	MONT_MAC(w0, w1, w2, a[22], b[23]);
-	MONT_MAC(t0, t1, t2, a[23], b[22]);
-	MONT_MAC(v0, v1, v2, a[24], b[21]);
-	MONT_MAC(w0, w1, w2, a[25], b[20]);
-	MONT_MAC(t0, t1, t2, a[26], b[19]);
-	MONT_MAC(v0, v1, v2, a[27], b[18]);
-	MONT_MAC(w0, w1, w2, a[28], b[17]);
-	MONT_MAC(t0, t1, t2, a[29], b[16]);
-	MONT_MAC(v0, v1, v2, a[30], b[15]);
-	MONT_MAC(w0, w1, w2, a[31], b[14]);
-	MONT_MAC(t0, t1, t2, u[14], m[31]);
-	MONT_MAC(v0, v1, v2, u[15], m[30]);
-	MONT_MAC(w0, w1, w2, u[16], m[29]);
-	MONT_MAC(t0, t1, t2, u[17], m[28]);
-	MONT_MAC(v0, v1, v2, u[18], m[27]);
-	MONT_MAC(w0, w1, w2, u[19], m[26]);
-	MONT_MAC(t0, t1, t2, u[20], m[25]);
-	MONT_MAC(v0, v1, v2, u[21], m[24]);
-	MONT_MAC(w0, w1, w2, u[22], m[23]);
-	MONT_MAC(t0, t1, t2, u[23], m[22]);
-	MONT_MAC(v0, v1, v2, u[24], m[21]);
-	MONT_MAC(w0, w1, w2, u[25], m[20]);
-	MONT_MAC(t0, t1, t2, u[26], m[19]);
-	MONT_MAC(v0, v1, v2, u[27], m[18]);
-	MONT_MAC(w0, w1, w2, u[28], m[17]);
-	MONT_MAC(t0, t1, t2, u[29], m[16]);
-	MONT_MAC(v0, v1, v2, u[30], m[15]);
-	MONT_MAC(w0, w1, w2, u[31], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 46 */
-	MONT_MAC(t0, t1, t2, a[15], b[31]);
-	MONT_MUL(v0, v1, v2, a[16], b[30]);
-	MONT_MUL(w0, w1, w2, a[17], b[29]);
-	MONT_MAC(t0, t1, t2, a[18], b[28]);
-	MONT_MAC(v0, v1, v2, a[19], b[27]);
-	MONT_MAC(w0, w1, w2, a[20], b[26]);
-	MONT_MAC(t0, t1, t2, a[21], b[25]);
-	MONT_MAC(v0, v1, v2, a[22], b[24]);
-	MONT_MAC(w0, w1, w2, a[23], b[23]);
-	MONT_MAC(t0, t1, t2, a[24], b[22]);
-	MONT_MAC(v0, v1, v2, a[25], b[21]);
-	MONT_MAC(w0, w1, w2, a[26], b[20]);
-	MONT_MAC(t0, t1, t2, a[27], b[19]);
-	MONT_MAC(v0, v1, v2, a[28], b[18]);
-	MONT_MAC(w0, w1, w2, a[29], b[17]);
-	MONT_MAC(t0, t1, t2, a[30], b[16]);
-	MONT_MAC(v0, v1, v2, a[31], b[15]);
-	MONT_MAC(w0, w1, w2, u[15], m[31]);
-	MONT_MAC(t0, t1, t2, u[16], m[30]);
-	MONT_MAC(v0, v1, v2, u[17], m[29]);
-	MONT_MAC(w0, w1, w2, u[18], m[28]);
-	MONT_MAC(t0, t1, t2, u[19], m[27]);
-	MONT_MAC(v0, v1, v2, u[20], m[26]);
-	MONT_MAC(w0, w1, w2, u[21], m[25]);
-	MONT_MAC(t0, t1, t2, u[22], m[24]);
-	MONT_MAC(v0, v1, v2, u[23], m[23]);
-	MONT_MAC(w0, w1, w2, u[24], m[22]);
-	MONT_MAC(t0, t1, t2, u[25], m[21]);
-	MONT_MAC(v0, v1, v2, u[26], m[20]);
-	MONT_MAC(w0, w1, w2, u[27], m[19]);
-	MONT_MAC(t0, t1, t2, u[28], m[18]);
-	MONT_MAC(v0, v1, v2, u[29], m[17]);
-	MONT_MAC(w0, w1, w2, u[30], m[16]);
-	MONT_MAC(t0, t1, t2, u[31], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[14] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 47 */
-	MONT_MAC(t0, t1, t2, a[16], b[31]);
-	MONT_MUL(v0, v1, v2, a[17], b[30]);
-	MONT_MUL(w0, w1, w2, a[18], b[29]);
-	MONT_MAC(t0, t1, t2, a[19], b[28]);
-	MONT_MAC(v0, v1, v2, a[20], b[27]);
-	MONT_MAC(w0, w1, w2, a[21], b[26]);
-	MONT_MAC(t0, t1, t2, a[22], b[25]);
-	MONT_MAC(v0, v1, v2, a[23], b[24]);
-	MONT_MAC(w0, w1, w2, a[24], b[23]);
-	MONT_MAC(t0, t1, t2, a[25], b[22]);
-	MONT_MAC(v0, v1, v2, a[26], b[21]);
-	MONT_MAC(w0, w1, w2, a[27], b[20]);
-	MONT_MAC(t0, t1, t2, a[28], b[19]);
-	MONT_MAC(v0, v1, v2, a[29], b[18]);
-	MONT_MAC(w0, w1, w2, a[30], b[17]);
-	MONT_MAC(t0, t1, t2, a[31], b[16]);
-	MONT_MAC(v0, v1, v2, u[16], m[31]);
-	MONT_MAC(w0, w1, w2, u[17], m[30]);
-	MONT_MAC(t0, t1, t2, u[18], m[29]);
-	MONT_MAC(v0, v1, v2, u[19], m[28]);
-	MONT_MAC(w0, w1, w2, u[20], m[27]);
-	MONT_MAC(t0, t1, t2, u[21], m[26]);
-	MONT_MAC(v0, v1, v2, u[22], m[25]);
-	MONT_MAC(w0, w1, w2, u[23], m[24]);
-	MONT_MAC(t0, t1, t2, u[24], m[23]);
-	MONT_MAC(v0, v1, v2, u[25], m[22]);
-	MONT_MAC(w0, w1, w2, u[26], m[21]);
-	MONT_MAC(t0, t1, t2, u[27], m[20]);
-	MONT_MAC(v0, v1, v2, u[28], m[19]);
-	MONT_MAC(w0, w1, w2, u[29], m[18]);
-	MONT_MAC(t0, t1, t2, u[30], m[17]);
-	MONT_MAC(v0, v1, v2, u[31], m[16]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[15] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 48 */
-	MONT_MAC(t0, t1, t2, a[17], b[31]);
-	MONT_MUL(v0, v1, v2, a[18], b[30]);
-	MONT_MUL(w0, w1, w2, a[19], b[29]);
-	MONT_MAC(t0, t1, t2, a[20], b[28]);
-	MONT_MAC(v0, v1, v2, a[21], b[27]);
-	MONT_MAC(w0, w1, w2, a[22], b[26]);
-	MONT_MAC(t0, t1, t2, a[23], b[25]);
-	MONT_MAC(v0, v1, v2, a[24], b[24]);
-	MONT_MAC(w0, w1, w2, a[25], b[23]);
-	MONT_MAC(t0, t1, t2, a[26], b[22]);
-	MONT_MAC(v0, v1, v2, a[27], b[21]);
-	MONT_MAC(w0, w1, w2, a[28], b[20]);
-	MONT_MAC(t0, t1, t2, a[29], b[19]);
-	MONT_MAC(v0, v1, v2, a[30], b[18]);
-	MONT_MAC(w0, w1, w2, a[31], b[17]);
-	MONT_MAC(t0, t1, t2, u[17], m[31]);
-	MONT_MAC(v0, v1, v2, u[18], m[30]);
-	MONT_MAC(w0, w1, w2, u[19], m[29]);
-	MONT_MAC(t0, t1, t2, u[20], m[28]);
-	MONT_MAC(v0, v1, v2, u[21], m[27]);
-	MONT_MAC(w0, w1, w2, u[22], m[26]);
-	MONT_MAC(t0, t1, t2, u[23], m[25]);
-	MONT_MAC(v0, v1, v2, u[24], m[24]);
-	MONT_MAC(w0, w1, w2, u[25], m[23]);
-	MONT_MAC(t0, t1, t2, u[26], m[22]);
-	MONT_MAC(v0, v1, v2, u[27], m[21]);
-	MONT_MAC(w0, w1, w2, u[28], m[20]);
-	MONT_MAC(t0, t1, t2, u[29], m[19]);
-	MONT_MAC(v0, v1, v2, u[30], m[18]);
-	MONT_MAC(w0, w1, w2, u[31], m[17]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[16] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 49 */
-	MONT_MAC(t0, t1, t2, a[18], b[31]);
-	MONT_MUL(v0, v1, v2, a[19], b[30]);
-	MONT_MUL(w0, w1, w2, a[20], b[29]);
-	MONT_MAC(t0, t1, t2, a[21], b[28]);
-	MONT_MAC(v0, v1, v2, a[22], b[27]);
-	MONT_MAC(w0, w1, w2, a[23], b[26]);
-	MONT_MAC(t0, t1, t2, a[24], b[25]);
-	MONT_MAC(v0, v1, v2, a[25], b[24]);
-	MONT_MAC(w0, w1, w2, a[26], b[23]);
-	MONT_MAC(t0, t1, t2, a[27], b[22]);
-	MONT_MAC(v0, v1, v2, a[28], b[21]);
-	MONT_MAC(w0, w1, w2, a[29], b[20]);
-	MONT_MAC(t0, t1, t2, a[30], b[19]);
-	MONT_MAC(v0, v1, v2, a[31], b[18]);
-	MONT_MAC(w0, w1, w2, u[18], m[31]);
-	MONT_MAC(t0, t1, t2, u[19], m[30]);
-	MONT_MAC(v0, v1, v2, u[20], m[29]);
-	MONT_MAC(w0, w1, w2, u[21], m[28]);
-	MONT_MAC(t0, t1, t2, u[22], m[27]);
-	MONT_MAC(v0, v1, v2, u[23], m[26]);
-	MONT_MAC(w0, w1, w2, u[24], m[25]);
-	MONT_MAC(t0, t1, t2, u[25], m[24]);
-	MONT_MAC(v0, v1, v2, u[26], m[23]);
-	MONT_MAC(w0, w1, w2, u[27], m[22]);
-	MONT_MAC(t0, t1, t2, u[28], m[21]);
-	MONT_MAC(v0, v1, v2, u[29], m[20]);
-	MONT_MAC(w0, w1, w2, u[30], m[19]);
-	MONT_MAC(t0, t1, t2, u[31], m[18]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[17] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 50 */
-	MONT_MAC(t0, t1, t2, a[19], b[31]);
-	MONT_MUL(v0, v1, v2, a[20], b[30]);
-	MONT_MUL(w0, w1, w2, a[21], b[29]);
-	MONT_MAC(t0, t1, t2, a[22], b[28]);
-	MONT_MAC(v0, v1, v2, a[23], b[27]);
-	MONT_MAC(w0, w1, w2, a[24], b[26]);
-	MONT_MAC(t0, t1, t2, a[25], b[25]);
-	MONT_MAC(v0, v1, v2, a[26], b[24]);
-	MONT_MAC(w0, w1, w2, a[27], b[23]);
-	MONT_MAC(t0, t1, t2, a[28], b[22]);
-	MONT_MAC(v0, v1, v2, a[29], b[21]);
-	MONT_MAC(w0, w1, w2, a[30], b[20]);
-	MONT_MAC(t0, t1, t2, a[31], b[19]);
-	MONT_MAC(v0, v1, v2, u[19], m[31]);
-	MONT_MAC(w0, w1, w2, u[20], m[30]);
-	MONT_MAC(t0, t1, t2, u[21], m[29]);
-	MONT_MAC(v0, v1, v2, u[22], m[28]);
-	MONT_MAC(w0, w1, w2, u[23], m[27]);
-	MONT_MAC(t0, t1, t2, u[24], m[26]);
-	MONT_MAC(v0, v1, v2, u[25], m[25]);
-	MONT_MAC(w0, w1, w2, u[26], m[24]);
-	MONT_MAC(t0, t1, t2, u[27], m[23]);
-	MONT_MAC(v0, v1, v2, u[28], m[22]);
-	MONT_MAC(w0, w1, w2, u[29], m[21]);
-	MONT_MAC(t0, t1, t2, u[30], m[20]);
-	MONT_MAC(v0, v1, v2, u[31], m[19]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[18] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 51 */
-	MONT_MAC(t0, t1, t2, a[20], b[31]);
-	MONT_MUL(v0, v1, v2, a[21], b[30]);
-	MONT_MUL(w0, w1, w2, a[22], b[29]);
-	MONT_MAC(t0, t1, t2, a[23], b[28]);
-	MONT_MAC(v0, v1, v2, a[24], b[27]);
-	MONT_MAC(w0, w1, w2, a[25], b[26]);
-	MONT_MAC(t0, t1, t2, a[26], b[25]);
-	MONT_MAC(v0, v1, v2, a[27], b[24]);
-	MONT_MAC(w0, w1, w2, a[28], b[23]);
-	MONT_MAC(t0, t1, t2, a[29], b[22]);
-	MONT_MAC(v0, v1, v2, a[30], b[21]);
-	MONT_MAC(w0, w1, w2, a[31], b[20]);
-	MONT_MAC(t0, t1, t2, u[20], m[31]);
-	MONT_MAC(v0, v1, v2, u[21], m[30]);
-	MONT_MAC(w0, w1, w2, u[22], m[29]);
-	MONT_MAC(t0, t1, t2, u[23], m[28]);
-	MONT_MAC(v0, v1, v2, u[24], m[27]);
-	MONT_MAC(w0, w1, w2, u[25], m[26]);
-	MONT_MAC(t0, t1, t2, u[26], m[25]);
-	MONT_MAC(v0, v1, v2, u[27], m[24]);
-	MONT_MAC(w0, w1, w2, u[28], m[23]);
-	MONT_MAC(t0, t1, t2, u[29], m[22]);
-	MONT_MAC(v0, v1, v2, u[30], m[21]);
-	MONT_MAC(w0, w1, w2, u[31], m[20]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[19] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 52 */
-	MONT_MAC(t0, t1, t2, a[21], b[31]);
-	MONT_MUL(v0, v1, v2, a[22], b[30]);
-	MONT_MUL(w0, w1, w2, a[23], b[29]);
-	MONT_MAC(t0, t1, t2, a[24], b[28]);
-	MONT_MAC(v0, v1, v2, a[25], b[27]);
-	MONT_MAC(w0, w1, w2, a[26], b[26]);
-	MONT_MAC(t0, t1, t2, a[27], b[25]);
-	MONT_MAC(v0, v1, v2, a[28], b[24]);
-	MONT_MAC(w0, w1, w2, a[29], b[23]);
-	MONT_MAC(t0, t1, t2, a[30], b[22]);
-	MONT_MAC(v0, v1, v2, a[31], b[21]);
-	MONT_MAC(w0, w1, w2, u[21], m[31]);
-	MONT_MAC(t0, t1, t2, u[22], m[30]);
-	MONT_MAC(v0, v1, v2, u[23], m[29]);
-	MONT_MAC(w0, w1, w2, u[24], m[28]);
-	MONT_MAC(t0, t1, t2, u[25], m[27]);
-	MONT_MAC(v0, v1, v2, u[26], m[26]);
-	MONT_MAC(w0, w1, w2, u[27], m[25]);
-	MONT_MAC(t0, t1, t2, u[28], m[24]);
-	MONT_MAC(v0, v1, v2, u[29], m[23]);
-	MONT_MAC(w0, w1, w2, u[30], m[22]);
-	MONT_MAC(t0, t1, t2, u[31], m[21]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[20] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 53 */
-	MONT_MAC(t0, t1, t2, a[22], b[31]);
-	MONT_MUL(v0, v1, v2, a[23], b[30]);
-	MONT_MUL(w0, w1, w2, a[24], b[29]);
-	MONT_MAC(t0, t1, t2, a[25], b[28]);
-	MONT_MAC(v0, v1, v2, a[26], b[27]);
-	MONT_MAC(w0, w1, w2, a[27], b[26]);
-	MONT_MAC(t0, t1, t2, a[28], b[25]);
-	MONT_MAC(v0, v1, v2, a[29], b[24]);
-	MONT_MAC(w0, w1, w2, a[30], b[23]);
-	MONT_MAC(t0, t1, t2, a[31], b[22]);
-	MONT_MAC(v0, v1, v2, u[22], m[31]);
-	MONT_MAC(w0, w1, w2, u[23], m[30]);
-	MONT_MAC(t0, t1, t2, u[24], m[29]);
-	MONT_MAC(v0, v1, v2, u[25], m[28]);
-	MONT_MAC(w0, w1, w2, u[26], m[27]);
-	MONT_MAC(t0, t1, t2, u[27], m[26]);
-	MONT_MAC(v0, v1, v2, u[28], m[25]);
-	MONT_MAC(w0, w1, w2, u[29], m[24]);
-	MONT_MAC(t0, t1, t2, u[30], m[23]);
-	MONT_MAC(v0, v1, v2, u[31], m[22]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[21] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 54 */
-	MONT_MAC(t0, t1, t2, a[23], b[31]);
-	MONT_MUL(v0, v1, v2, a[24], b[30]);
-	MONT_MUL(w0, w1, w2, a[25], b[29]);
-	MONT_MAC(t0, t1, t2, a[26], b[28]);
-	MONT_MAC(v0, v1, v2, a[27], b[27]);
-	MONT_MAC(w0, w1, w2, a[28], b[26]);
-	MONT_MAC(t0, t1, t2, a[29], b[25]);
-	MONT_MAC(v0, v1, v2, a[30], b[24]);
-	MONT_MAC(w0, w1, w2, a[31], b[23]);
-	MONT_MAC(t0, t1, t2, u[23], m[31]);
-	MONT_MAC(v0, v1, v2, u[24], m[30]);
-	MONT_MAC(w0, w1, w2, u[25], m[29]);
-	MONT_MAC(t0, t1, t2, u[26], m[28]);
-	MONT_MAC(v0, v1, v2, u[27], m[27]);
-	MONT_MAC(w0, w1, w2, u[28], m[26]);
-	MONT_MAC(t0, t1, t2, u[29], m[25]);
-	MONT_MAC(v0, v1, v2, u[30], m[24]);
-	MONT_MAC(w0, w1, w2, u[31], m[23]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[22] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 55 */
-	MONT_MAC(t0, t1, t2, a[24], b[31]);
-	MONT_MUL(v0, v1, v2, a[25], b[30]);
-	MONT_MUL(w0, w1, w2, a[26], b[29]);
-	MONT_MAC(t0, t1, t2, a[27], b[28]);
-	MONT_MAC(v0, v1, v2, a[28], b[27]);
-	MONT_MAC(w0, w1, w2, a[29], b[26]);
-	MONT_MAC(t0, t1, t2, a[30], b[25]);
-	MONT_MAC(v0, v1, v2, a[31], b[24]);
-	MONT_MAC(w0, w1, w2, u[24], m[31]);
-	MONT_MAC(t0, t1, t2, u[25], m[30]);
-	MONT_MAC(v0, v1, v2, u[26], m[29]);
-	MONT_MAC(w0, w1, w2, u[27], m[28]);
-	MONT_MAC(t0, t1, t2, u[28], m[27]);
-	MONT_MAC(v0, v1, v2, u[29], m[26]);
-	MONT_MAC(w0, w1, w2, u[30], m[25]);
-	MONT_MAC(t0, t1, t2, u[31], m[24]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[23] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 56 */
-	MONT_MAC(t0, t1, t2, a[25], b[31]);
-	MONT_MUL(v0, v1, v2, a[26], b[30]);
-	MONT_MUL(w0, w1, w2, a[27], b[29]);
-	MONT_MAC(t0, t1, t2, a[28], b[28]);
-	MONT_MAC(v0, v1, v2, a[29], b[27]);
-	MONT_MAC(w0, w1, w2, a[30], b[26]);
-	MONT_MAC(t0, t1, t2, a[31], b[25]);
-	MONT_MAC(v0, v1, v2, u[25], m[31]);
-	MONT_MAC(w0, w1, w2, u[26], m[30]);
-	MONT_MAC(t0, t1, t2, u[27], m[29]);
-	MONT_MAC(v0, v1, v2, u[28], m[28]);
-	MONT_MAC(w0, w1, w2, u[29], m[27]);
-	MONT_MAC(t0, t1, t2, u[30], m[26]);
-	MONT_MAC(v0, v1, v2, u[31], m[25]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[24] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 57 */
-	MONT_MAC(t0, t1, t2, a[26], b[31]);
-	MONT_MUL(v0, v1, v2, a[27], b[30]);
-	MONT_MUL(w0, w1, w2, a[28], b[29]);
-	MONT_MAC(t0, t1, t2, a[29], b[28]);
-	MONT_MAC(v0, v1, v2, a[30], b[27]);
-	MONT_MAC(w0, w1, w2, a[31], b[26]);
-	MONT_MAC(t0, t1, t2, u[26], m[31]);
-	MONT_MAC(v0, v1, v2, u[27], m[30]);
-	MONT_MAC(w0, w1, w2, u[28], m[29]);
-	MONT_MAC(t0, t1, t2, u[29], m[28]);
-	MONT_MAC(v0, v1, v2, u[30], m[27]);
-	MONT_MAC(w0, w1, w2, u[31], m[26]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[25] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 58 */
-	MONT_MAC(t0, t1, t2, a[27], b[31]);
-	MONT_MUL(v0, v1, v2, a[28], b[30]);
-	MONT_MUL(w0, w1, w2, a[29], b[29]);
-	MONT_MAC(t0, t1, t2, a[30], b[28]);
-	MONT_MAC(v0, v1, v2, a[31], b[27]);
-	MONT_MAC(w0, w1, w2, u[27], m[31]);
-	MONT_MAC(t0, t1, t2, u[28], m[30]);
-	MONT_MAC(v0, v1, v2, u[29], m[29]);
-	MONT_MAC(w0, w1, w2, u[30], m[28]);
-	MONT_MAC(t0, t1, t2, u[31], m[27]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[26] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 59 */
-	MONT_MAC(t0, t1, t2, a[28], b[31]);
-	MONT_MUL(v0, v1, v2, a[29], b[30]);
-	MONT_MUL(w0, w1, w2, a[30], b[29]);
-	MONT_MAC(t0, t1, t2, a[31], b[28]);
-	MONT_MAC(v0, v1, v2, u[28], m[31]);
-	MONT_MAC(w0, w1, w2, u[29], m[30]);
-	MONT_MAC(t0, t1, t2, u[30], m[29]);
-	MONT_MAC(v0, v1, v2, u[31], m[28]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[27] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 60 */
-	MONT_MAC(t0, t1, t2, a[29], b[31]);
-	MONT_MUL(v0, v1, v2, a[30], b[30]);
-	MONT_MUL(w0, w1, w2, a[31], b[29]);
-	MONT_MAC(t0, t1, t2, u[29], m[31]);
-	MONT_MAC(v0, v1, v2, u[30], m[30]);
-	MONT_MAC(w0, w1, w2, u[31], m[29]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[28] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 61 */
-	MONT_MAC(t0, t1, t2, a[30], b[31]);
-	MONT_MUL(v0, v1, v2, a[31], b[30]);
-	MONT_MUL(w0, w1, w2, u[30], m[31]);
-	MONT_MAC(t0, t1, t2, u[31], m[30]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	z[29] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 62 */
-	MONT_MAC(t0, t1, t2, a[31], b[31]);
-	MONT_MUL(v0, v1, v2, u[31], m[31]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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);
-}
-
-/* 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, v0, v1, v2, w0, w1, w2, borrow, take;
-	limb_t s0, s1, s2, c0, c1, c2;
-
-	/* column 0 */
-	MONT_MAC(t0, t1, t2, a[0], a[0]);
-	u[0] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[0], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 1 */
-	MONT_MUL(s0, s1, s2, a[0], a[1]);
-	MONT_MAC(t0, t1, t2, u[0], m[1]);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[1] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[1], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 2 */
-	MONT_MUL(s0, s1, s2, a[0], a[2]);
-	MONT_MAC(t0, t1, t2, a[1], a[1]);
-	MONT_MUL(v0, v1, v2, u[0], m[2]);
-	MONT_MUL(w0, w1, w2, u[1], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[2] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[2], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 3 */
-	MONT_MUL(s0, s1, s2, a[0], a[3]);
-	MONT_MUL(c0, c1, c2, a[1], a[2]);
-	MONT_MAC(t0, t1, t2, u[0], m[3]);
-	MONT_MUL(v0, v1, v2, u[1], m[2]);
-	MONT_MUL(w0, w1, w2, u[2], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[3] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[3], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 4 */
-	MONT_MUL(s0, s1, s2, a[0], a[4]);
-	MONT_MUL(c0, c1, c2, a[1], a[3]);
-	MONT_MAC(t0, t1, t2, a[2], a[2]);
-	MONT_MUL(v0, v1, v2, u[0], m[4]);
-	MONT_MUL(w0, w1, w2, u[1], m[3]);
-	MONT_MAC(t0, t1, t2, u[2], m[2]);
-	MONT_MAC(v0, v1, v2, u[3], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[4] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[4], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 5 */
-	MONT_MUL(s0, s1, s2, a[0], a[5]);
-	MONT_MUL(c0, c1, c2, a[1], a[4]);
-	MONT_MAC(s0, s1, s2, a[2], a[3]);
-	MONT_MAC(t0, t1, t2, u[0], m[5]);
-	MONT_MUL(v0, v1, v2, u[1], m[4]);
-	MONT_MUL(w0, w1, w2, u[2], m[3]);
-	MONT_MAC(t0, t1, t2, u[3], m[2]);
-	MONT_MAC(v0, v1, v2, u[4], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[5] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[5], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 6 */
-	MONT_MUL(s0, s1, s2, a[0], a[6]);
-	MONT_MUL(c0, c1, c2, a[1], a[5]);
-	MONT_MAC(s0, s1, s2, a[2], a[4]);
-	MONT_MAC(t0, t1, t2, a[3], a[3]);
-	MONT_MUL(v0, v1, v2, u[0], m[6]);
-	MONT_MUL(w0, w1, w2, u[1], m[5]);
-	MONT_MAC(t0, t1, t2, u[2], m[4]);
-	MONT_MAC(v0, v1, v2, u[3], m[3]);
-	MONT_MAC(w0, w1, w2, u[4], m[2]);
-	MONT_MAC(t0, t1, t2, u[5], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[6] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[6], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 7 */
-	MONT_MUL(s0, s1, s2, a[0], a[7]);
-	MONT_MUL(c0, c1, c2, a[1], a[6]);
-	MONT_MAC(s0, s1, s2, a[2], a[5]);
-	MONT_MAC(c0, c1, c2, a[3], a[4]);
-	MONT_MAC(t0, t1, t2, u[0], m[7]);
-	MONT_MUL(v0, v1, v2, u[1], m[6]);
-	MONT_MUL(w0, w1, w2, u[2], m[5]);
-	MONT_MAC(t0, t1, t2, u[3], m[4]);
-	MONT_MAC(v0, v1, v2, u[4], m[3]);
-	MONT_MAC(w0, w1, w2, u[5], m[2]);
-	MONT_MAC(t0, t1, t2, u[6], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[7] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[7], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 8 */
-	MONT_MUL(s0, s1, s2, a[0], a[8]);
-	MONT_MUL(c0, c1, c2, a[1], a[7]);
-	MONT_MAC(s0, s1, s2, a[2], a[6]);
-	MONT_MAC(c0, c1, c2, a[3], a[5]);
-	MONT_MAC(t0, t1, t2, a[4], a[4]);
-	MONT_MUL(v0, v1, v2, u[0], m[8]);
-	MONT_MUL(w0, w1, w2, u[1], m[7]);
-	MONT_MAC(t0, t1, t2, u[2], m[6]);
-	MONT_MAC(v0, v1, v2, u[3], m[5]);
-	MONT_MAC(w0, w1, w2, u[4], m[4]);
-	MONT_MAC(t0, t1, t2, u[5], m[3]);
-	MONT_MAC(v0, v1, v2, u[6], m[2]);
-	MONT_MAC(w0, w1, w2, u[7], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[8] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[8], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 9 */
-	MONT_MUL(s0, s1, s2, a[0], a[9]);
-	MONT_MUL(c0, c1, c2, a[1], a[8]);
-	MONT_MAC(s0, s1, s2, a[2], a[7]);
-	MONT_MAC(c0, c1, c2, a[3], a[6]);
-	MONT_MAC(s0, s1, s2, a[4], a[5]);
-	MONT_MAC(t0, t1, t2, u[0], m[9]);
-	MONT_MUL(v0, v1, v2, u[1], m[8]);
-	MONT_MUL(w0, w1, w2, u[2], m[7]);
-	MONT_MAC(t0, t1, t2, u[3], m[6]);
-	MONT_MAC(v0, v1, v2, u[4], m[5]);
-	MONT_MAC(w0, w1, w2, u[5], m[4]);
-	MONT_MAC(t0, t1, t2, u[6], m[3]);
-	MONT_MAC(v0, v1, v2, u[7], m[2]);
-	MONT_MAC(w0, w1, w2, u[8], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[9] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[9], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 10 */
-	MONT_MUL(s0, s1, s2, a[0], a[10]);
-	MONT_MUL(c0, c1, c2, a[1], a[9]);
-	MONT_MAC(s0, s1, s2, a[2], a[8]);
-	MONT_MAC(c0, c1, c2, a[3], a[7]);
-	MONT_MAC(s0, s1, s2, a[4], a[6]);
-	MONT_MAC(t0, t1, t2, a[5], a[5]);
-	MONT_MUL(v0, v1, v2, u[0], m[10]);
-	MONT_MUL(w0, w1, w2, u[1], m[9]);
-	MONT_MAC(t0, t1, t2, u[2], m[8]);
-	MONT_MAC(v0, v1, v2, u[3], m[7]);
-	MONT_MAC(w0, w1, w2, u[4], m[6]);
-	MONT_MAC(t0, t1, t2, u[5], m[5]);
-	MONT_MAC(v0, v1, v2, u[6], m[4]);
-	MONT_MAC(w0, w1, w2, u[7], m[3]);
-	MONT_MAC(t0, t1, t2, u[8], m[2]);
-	MONT_MAC(v0, v1, v2, u[9], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[10] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[10], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 11 */
-	MONT_MUL(s0, s1, s2, a[0], a[11]);
-	MONT_MUL(c0, c1, c2, a[1], a[10]);
-	MONT_MAC(s0, s1, s2, a[2], a[9]);
-	MONT_MAC(c0, c1, c2, a[3], a[8]);
-	MONT_MAC(s0, s1, s2, a[4], a[7]);
-	MONT_MAC(c0, c1, c2, a[5], a[6]);
-	MONT_MAC(t0, t1, t2, u[0], m[11]);
-	MONT_MUL(v0, v1, v2, u[1], m[10]);
-	MONT_MUL(w0, w1, w2, u[2], m[9]);
-	MONT_MAC(t0, t1, t2, u[3], m[8]);
-	MONT_MAC(v0, v1, v2, u[4], m[7]);
-	MONT_MAC(w0, w1, w2, u[5], m[6]);
-	MONT_MAC(t0, t1, t2, u[6], m[5]);
-	MONT_MAC(v0, v1, v2, u[7], m[4]);
-	MONT_MAC(w0, w1, w2, u[8], m[3]);
-	MONT_MAC(t0, t1, t2, u[9], m[2]);
-	MONT_MAC(v0, v1, v2, u[10], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[11] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[11], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 12 */
-	MONT_MUL(s0, s1, s2, a[0], a[12]);
-	MONT_MUL(c0, c1, c2, a[1], a[11]);
-	MONT_MAC(s0, s1, s2, a[2], a[10]);
-	MONT_MAC(c0, c1, c2, a[3], a[9]);
-	MONT_MAC(s0, s1, s2, a[4], a[8]);
-	MONT_MAC(c0, c1, c2, a[5], a[7]);
-	MONT_MAC(t0, t1, t2, a[6], a[6]);
-	MONT_MUL(v0, v1, v2, u[0], m[12]);
-	MONT_MUL(w0, w1, w2, u[1], m[11]);
-	MONT_MAC(t0, t1, t2, u[2], m[10]);
-	MONT_MAC(v0, v1, v2, u[3], m[9]);
-	MONT_MAC(w0, w1, w2, u[4], m[8]);
-	MONT_MAC(t0, t1, t2, u[5], m[7]);
-	MONT_MAC(v0, v1, v2, u[6], m[6]);
-	MONT_MAC(w0, w1, w2, u[7], m[5]);
-	MONT_MAC(t0, t1, t2, u[8], m[4]);
-	MONT_MAC(v0, v1, v2, u[9], m[3]);
-	MONT_MAC(w0, w1, w2, u[10], m[2]);
-	MONT_MAC(t0, t1, t2, u[11], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[12] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[12], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 13 */
-	MONT_MUL(s0, s1, s2, a[0], a[13]);
-	MONT_MUL(c0, c1, c2, a[1], a[12]);
-	MONT_MAC(s0, s1, s2, a[2], a[11]);
-	MONT_MAC(c0, c1, c2, a[3], a[10]);
-	MONT_MAC(s0, s1, s2, a[4], a[9]);
-	MONT_MAC(c0, c1, c2, a[5], a[8]);
-	MONT_MAC(s0, s1, s2, a[6], a[7]);
-	MONT_MAC(t0, t1, t2, u[0], m[13]);
-	MONT_MUL(v0, v1, v2, u[1], m[12]);
-	MONT_MUL(w0, w1, w2, u[2], m[11]);
-	MONT_MAC(t0, t1, t2, u[3], m[10]);
-	MONT_MAC(v0, v1, v2, u[4], m[9]);
-	MONT_MAC(w0, w1, w2, u[5], m[8]);
-	MONT_MAC(t0, t1, t2, u[6], m[7]);
-	MONT_MAC(v0, v1, v2, u[7], m[6]);
-	MONT_MAC(w0, w1, w2, u[8], m[5]);
-	MONT_MAC(t0, t1, t2, u[9], m[4]);
-	MONT_MAC(v0, v1, v2, u[10], m[3]);
-	MONT_MAC(w0, w1, w2, u[11], m[2]);
-	MONT_MAC(t0, t1, t2, u[12], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[13] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[13], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 14 */
-	MONT_MUL(s0, s1, s2, a[0], a[14]);
-	MONT_MUL(c0, c1, c2, a[1], a[13]);
-	MONT_MAC(s0, s1, s2, a[2], a[12]);
-	MONT_MAC(c0, c1, c2, a[3], a[11]);
-	MONT_MAC(s0, s1, s2, a[4], a[10]);
-	MONT_MAC(c0, c1, c2, a[5], a[9]);
-	MONT_MAC(s0, s1, s2, a[6], a[8]);
-	MONT_MAC(t0, t1, t2, a[7], a[7]);
-	MONT_MUL(v0, v1, v2, u[0], m[14]);
-	MONT_MUL(w0, w1, w2, u[1], m[13]);
-	MONT_MAC(t0, t1, t2, u[2], m[12]);
-	MONT_MAC(v0, v1, v2, u[3], m[11]);
-	MONT_MAC(w0, w1, w2, u[4], m[10]);
-	MONT_MAC(t0, t1, t2, u[5], m[9]);
-	MONT_MAC(v0, v1, v2, u[6], m[8]);
-	MONT_MAC(w0, w1, w2, u[7], m[7]);
-	MONT_MAC(t0, t1, t2, u[8], m[6]);
-	MONT_MAC(v0, v1, v2, u[9], m[5]);
-	MONT_MAC(w0, w1, w2, u[10], m[4]);
-	MONT_MAC(t0, t1, t2, u[11], m[3]);
-	MONT_MAC(v0, v1, v2, u[12], m[2]);
-	MONT_MAC(w0, w1, w2, u[13], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[14] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[14], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 15 */
-	MONT_MUL(s0, s1, s2, a[0], a[15]);
-	MONT_MUL(c0, c1, c2, a[1], a[14]);
-	MONT_MAC(s0, s1, s2, a[2], a[13]);
-	MONT_MAC(c0, c1, c2, a[3], a[12]);
-	MONT_MAC(s0, s1, s2, a[4], a[11]);
-	MONT_MAC(c0, c1, c2, a[5], a[10]);
-	MONT_MAC(s0, s1, s2, a[6], a[9]);
-	MONT_MAC(c0, c1, c2, a[7], a[8]);
-	MONT_MAC(t0, t1, t2, u[0], m[15]);
-	MONT_MUL(v0, v1, v2, u[1], m[14]);
-	MONT_MUL(w0, w1, w2, u[2], m[13]);
-	MONT_MAC(t0, t1, t2, u[3], m[12]);
-	MONT_MAC(v0, v1, v2, u[4], m[11]);
-	MONT_MAC(w0, w1, w2, u[5], m[10]);
-	MONT_MAC(t0, t1, t2, u[6], m[9]);
-	MONT_MAC(v0, v1, v2, u[7], m[8]);
-	MONT_MAC(w0, w1, w2, u[8], m[7]);
-	MONT_MAC(t0, t1, t2, u[9], m[6]);
-	MONT_MAC(v0, v1, v2, u[10], m[5]);
-	MONT_MAC(w0, w1, w2, u[11], m[4]);
-	MONT_MAC(t0, t1, t2, u[12], m[3]);
-	MONT_MAC(v0, v1, v2, u[13], m[2]);
-	MONT_MAC(w0, w1, w2, u[14], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[15] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[15], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 16 */
-	MONT_MUL(s0, s1, s2, a[0], a[16]);
-	MONT_MUL(c0, c1, c2, a[1], a[15]);
-	MONT_MAC(s0, s1, s2, a[2], a[14]);
-	MONT_MAC(c0, c1, c2, a[3], a[13]);
-	MONT_MAC(s0, s1, s2, a[4], a[12]);
-	MONT_MAC(c0, c1, c2, a[5], a[11]);
-	MONT_MAC(s0, s1, s2, a[6], a[10]);
-	MONT_MAC(c0, c1, c2, a[7], a[9]);
-	MONT_MAC(t0, t1, t2, a[8], a[8]);
-	MONT_MUL(v0, v1, v2, u[0], m[16]);
-	MONT_MUL(w0, w1, w2, u[1], m[15]);
-	MONT_MAC(t0, t1, t2, u[2], m[14]);
-	MONT_MAC(v0, v1, v2, u[3], m[13]);
-	MONT_MAC(w0, w1, w2, u[4], m[12]);
-	MONT_MAC(t0, t1, t2, u[5], m[11]);
-	MONT_MAC(v0, v1, v2, u[6], m[10]);
-	MONT_MAC(w0, w1, w2, u[7], m[9]);
-	MONT_MAC(t0, t1, t2, u[8], m[8]);
-	MONT_MAC(v0, v1, v2, u[9], m[7]);
-	MONT_MAC(w0, w1, w2, u[10], m[6]);
-	MONT_MAC(t0, t1, t2, u[11], m[5]);
-	MONT_MAC(v0, v1, v2, u[12], m[4]);
-	MONT_MAC(w0, w1, w2, u[13], m[3]);
-	MONT_MAC(t0, t1, t2, u[14], m[2]);
-	MONT_MAC(v0, v1, v2, u[15], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[16] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[16], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 17 */
-	MONT_MUL(s0, s1, s2, a[0], a[17]);
-	MONT_MUL(c0, c1, c2, a[1], a[16]);
-	MONT_MAC(s0, s1, s2, a[2], a[15]);
-	MONT_MAC(c0, c1, c2, a[3], a[14]);
-	MONT_MAC(s0, s1, s2, a[4], a[13]);
-	MONT_MAC(c0, c1, c2, a[5], a[12]);
-	MONT_MAC(s0, s1, s2, a[6], a[11]);
-	MONT_MAC(c0, c1, c2, a[7], a[10]);
-	MONT_MAC(s0, s1, s2, a[8], a[9]);
-	MONT_MAC(t0, t1, t2, u[0], m[17]);
-	MONT_MUL(v0, v1, v2, u[1], m[16]);
-	MONT_MUL(w0, w1, w2, u[2], m[15]);
-	MONT_MAC(t0, t1, t2, u[3], m[14]);
-	MONT_MAC(v0, v1, v2, u[4], m[13]);
-	MONT_MAC(w0, w1, w2, u[5], m[12]);
-	MONT_MAC(t0, t1, t2, u[6], m[11]);
-	MONT_MAC(v0, v1, v2, u[7], m[10]);
-	MONT_MAC(w0, w1, w2, u[8], m[9]);
-	MONT_MAC(t0, t1, t2, u[9], m[8]);
-	MONT_MAC(v0, v1, v2, u[10], m[7]);
-	MONT_MAC(w0, w1, w2, u[11], m[6]);
-	MONT_MAC(t0, t1, t2, u[12], m[5]);
-	MONT_MAC(v0, v1, v2, u[13], m[4]);
-	MONT_MAC(w0, w1, w2, u[14], m[3]);
-	MONT_MAC(t0, t1, t2, u[15], m[2]);
-	MONT_MAC(v0, v1, v2, u[16], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[17] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[17], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 18 */
-	MONT_MUL(s0, s1, s2, a[0], a[18]);
-	MONT_MUL(c0, c1, c2, a[1], a[17]);
-	MONT_MAC(s0, s1, s2, a[2], a[16]);
-	MONT_MAC(c0, c1, c2, a[3], a[15]);
-	MONT_MAC(s0, s1, s2, a[4], a[14]);
-	MONT_MAC(c0, c1, c2, a[5], a[13]);
-	MONT_MAC(s0, s1, s2, a[6], a[12]);
-	MONT_MAC(c0, c1, c2, a[7], a[11]);
-	MONT_MAC(s0, s1, s2, a[8], a[10]);
-	MONT_MAC(t0, t1, t2, a[9], a[9]);
-	MONT_MUL(v0, v1, v2, u[0], m[18]);
-	MONT_MUL(w0, w1, w2, u[1], m[17]);
-	MONT_MAC(t0, t1, t2, u[2], m[16]);
-	MONT_MAC(v0, v1, v2, u[3], m[15]);
-	MONT_MAC(w0, w1, w2, u[4], m[14]);
-	MONT_MAC(t0, t1, t2, u[5], m[13]);
-	MONT_MAC(v0, v1, v2, u[6], m[12]);
-	MONT_MAC(w0, w1, w2, u[7], m[11]);
-	MONT_MAC(t0, t1, t2, u[8], m[10]);
-	MONT_MAC(v0, v1, v2, u[9], m[9]);
-	MONT_MAC(w0, w1, w2, u[10], m[8]);
-	MONT_MAC(t0, t1, t2, u[11], m[7]);
-	MONT_MAC(v0, v1, v2, u[12], m[6]);
-	MONT_MAC(w0, w1, w2, u[13], m[5]);
-	MONT_MAC(t0, t1, t2, u[14], m[4]);
-	MONT_MAC(v0, v1, v2, u[15], m[3]);
-	MONT_MAC(w0, w1, w2, u[16], m[2]);
-	MONT_MAC(t0, t1, t2, u[17], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[18] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[18], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 19 */
-	MONT_MUL(s0, s1, s2, a[0], a[19]);
-	MONT_MUL(c0, c1, c2, a[1], a[18]);
-	MONT_MAC(s0, s1, s2, a[2], a[17]);
-	MONT_MAC(c0, c1, c2, a[3], a[16]);
-	MONT_MAC(s0, s1, s2, a[4], a[15]);
-	MONT_MAC(c0, c1, c2, a[5], a[14]);
-	MONT_MAC(s0, s1, s2, a[6], a[13]);
-	MONT_MAC(c0, c1, c2, a[7], a[12]);
-	MONT_MAC(s0, s1, s2, a[8], a[11]);
-	MONT_MAC(c0, c1, c2, a[9], a[10]);
-	MONT_MAC(t0, t1, t2, u[0], m[19]);
-	MONT_MUL(v0, v1, v2, u[1], m[18]);
-	MONT_MUL(w0, w1, w2, u[2], m[17]);
-	MONT_MAC(t0, t1, t2, u[3], m[16]);
-	MONT_MAC(v0, v1, v2, u[4], m[15]);
-	MONT_MAC(w0, w1, w2, u[5], m[14]);
-	MONT_MAC(t0, t1, t2, u[6], m[13]);
-	MONT_MAC(v0, v1, v2, u[7], m[12]);
-	MONT_MAC(w0, w1, w2, u[8], m[11]);
-	MONT_MAC(t0, t1, t2, u[9], m[10]);
-	MONT_MAC(v0, v1, v2, u[10], m[9]);
-	MONT_MAC(w0, w1, w2, u[11], m[8]);
-	MONT_MAC(t0, t1, t2, u[12], m[7]);
-	MONT_MAC(v0, v1, v2, u[13], m[6]);
-	MONT_MAC(w0, w1, w2, u[14], m[5]);
-	MONT_MAC(t0, t1, t2, u[15], m[4]);
-	MONT_MAC(v0, v1, v2, u[16], m[3]);
-	MONT_MAC(w0, w1, w2, u[17], m[2]);
-	MONT_MAC(t0, t1, t2, u[18], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[19] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[19], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 20 */
-	MONT_MUL(s0, s1, s2, a[0], a[20]);
-	MONT_MUL(c0, c1, c2, a[1], a[19]);
-	MONT_MAC(s0, s1, s2, a[2], a[18]);
-	MONT_MAC(c0, c1, c2, a[3], a[17]);
-	MONT_MAC(s0, s1, s2, a[4], a[16]);
-	MONT_MAC(c0, c1, c2, a[5], a[15]);
-	MONT_MAC(s0, s1, s2, a[6], a[14]);
-	MONT_MAC(c0, c1, c2, a[7], a[13]);
-	MONT_MAC(s0, s1, s2, a[8], a[12]);
-	MONT_MAC(c0, c1, c2, a[9], a[11]);
-	MONT_MAC(t0, t1, t2, a[10], a[10]);
-	MONT_MUL(v0, v1, v2, u[0], m[20]);
-	MONT_MUL(w0, w1, w2, u[1], m[19]);
-	MONT_MAC(t0, t1, t2, u[2], m[18]);
-	MONT_MAC(v0, v1, v2, u[3], m[17]);
-	MONT_MAC(w0, w1, w2, u[4], m[16]);
-	MONT_MAC(t0, t1, t2, u[5], m[15]);
-	MONT_MAC(v0, v1, v2, u[6], m[14]);
-	MONT_MAC(w0, w1, w2, u[7], m[13]);
-	MONT_MAC(t0, t1, t2, u[8], m[12]);
-	MONT_MAC(v0, v1, v2, u[9], m[11]);
-	MONT_MAC(w0, w1, w2, u[10], m[10]);
-	MONT_MAC(t0, t1, t2, u[11], m[9]);
-	MONT_MAC(v0, v1, v2, u[12], m[8]);
-	MONT_MAC(w0, w1, w2, u[13], m[7]);
-	MONT_MAC(t0, t1, t2, u[14], m[6]);
-	MONT_MAC(v0, v1, v2, u[15], m[5]);
-	MONT_MAC(w0, w1, w2, u[16], m[4]);
-	MONT_MAC(t0, t1, t2, u[17], m[3]);
-	MONT_MAC(v0, v1, v2, u[18], m[2]);
-	MONT_MAC(w0, w1, w2, u[19], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[20] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[20], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 21 */
-	MONT_MUL(s0, s1, s2, a[0], a[21]);
-	MONT_MUL(c0, c1, c2, a[1], a[20]);
-	MONT_MAC(s0, s1, s2, a[2], a[19]);
-	MONT_MAC(c0, c1, c2, a[3], a[18]);
-	MONT_MAC(s0, s1, s2, a[4], a[17]);
-	MONT_MAC(c0, c1, c2, a[5], a[16]);
-	MONT_MAC(s0, s1, s2, a[6], a[15]);
-	MONT_MAC(c0, c1, c2, a[7], a[14]);
-	MONT_MAC(s0, s1, s2, a[8], a[13]);
-	MONT_MAC(c0, c1, c2, a[9], a[12]);
-	MONT_MAC(s0, s1, s2, a[10], a[11]);
-	MONT_MAC(t0, t1, t2, u[0], m[21]);
-	MONT_MUL(v0, v1, v2, u[1], m[20]);
-	MONT_MUL(w0, w1, w2, u[2], m[19]);
-	MONT_MAC(t0, t1, t2, u[3], m[18]);
-	MONT_MAC(v0, v1, v2, u[4], m[17]);
-	MONT_MAC(w0, w1, w2, u[5], m[16]);
-	MONT_MAC(t0, t1, t2, u[6], m[15]);
-	MONT_MAC(v0, v1, v2, u[7], m[14]);
-	MONT_MAC(w0, w1, w2, u[8], m[13]);
-	MONT_MAC(t0, t1, t2, u[9], m[12]);
-	MONT_MAC(v0, v1, v2, u[10], m[11]);
-	MONT_MAC(w0, w1, w2, u[11], m[10]);
-	MONT_MAC(t0, t1, t2, u[12], m[9]);
-	MONT_MAC(v0, v1, v2, u[13], m[8]);
-	MONT_MAC(w0, w1, w2, u[14], m[7]);
-	MONT_MAC(t0, t1, t2, u[15], m[6]);
-	MONT_MAC(v0, v1, v2, u[16], m[5]);
-	MONT_MAC(w0, w1, w2, u[17], m[4]);
-	MONT_MAC(t0, t1, t2, u[18], m[3]);
-	MONT_MAC(v0, v1, v2, u[19], m[2]);
-	MONT_MAC(w0, w1, w2, u[20], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[21] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[21], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 22 */
-	MONT_MUL(s0, s1, s2, a[0], a[22]);
-	MONT_MUL(c0, c1, c2, a[1], a[21]);
-	MONT_MAC(s0, s1, s2, a[2], a[20]);
-	MONT_MAC(c0, c1, c2, a[3], a[19]);
-	MONT_MAC(s0, s1, s2, a[4], a[18]);
-	MONT_MAC(c0, c1, c2, a[5], a[17]);
-	MONT_MAC(s0, s1, s2, a[6], a[16]);
-	MONT_MAC(c0, c1, c2, a[7], a[15]);
-	MONT_MAC(s0, s1, s2, a[8], a[14]);
-	MONT_MAC(c0, c1, c2, a[9], a[13]);
-	MONT_MAC(s0, s1, s2, a[10], a[12]);
-	MONT_MAC(t0, t1, t2, a[11], a[11]);
-	MONT_MUL(v0, v1, v2, u[0], m[22]);
-	MONT_MUL(w0, w1, w2, u[1], m[21]);
-	MONT_MAC(t0, t1, t2, u[2], m[20]);
-	MONT_MAC(v0, v1, v2, u[3], m[19]);
-	MONT_MAC(w0, w1, w2, u[4], m[18]);
-	MONT_MAC(t0, t1, t2, u[5], m[17]);
-	MONT_MAC(v0, v1, v2, u[6], m[16]);
-	MONT_MAC(w0, w1, w2, u[7], m[15]);
-	MONT_MAC(t0, t1, t2, u[8], m[14]);
-	MONT_MAC(v0, v1, v2, u[9], m[13]);
-	MONT_MAC(w0, w1, w2, u[10], m[12]);
-	MONT_MAC(t0, t1, t2, u[11], m[11]);
-	MONT_MAC(v0, v1, v2, u[12], m[10]);
-	MONT_MAC(w0, w1, w2, u[13], m[9]);
-	MONT_MAC(t0, t1, t2, u[14], m[8]);
-	MONT_MAC(v0, v1, v2, u[15], m[7]);
-	MONT_MAC(w0, w1, w2, u[16], m[6]);
-	MONT_MAC(t0, t1, t2, u[17], m[5]);
-	MONT_MAC(v0, v1, v2, u[18], m[4]);
-	MONT_MAC(w0, w1, w2, u[19], m[3]);
-	MONT_MAC(t0, t1, t2, u[20], m[2]);
-	MONT_MAC(v0, v1, v2, u[21], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[22] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[22], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 23 */
-	MONT_MUL(s0, s1, s2, a[0], a[23]);
-	MONT_MUL(c0, c1, c2, a[1], a[22]);
-	MONT_MAC(s0, s1, s2, a[2], a[21]);
-	MONT_MAC(c0, c1, c2, a[3], a[20]);
-	MONT_MAC(s0, s1, s2, a[4], a[19]);
-	MONT_MAC(c0, c1, c2, a[5], a[18]);
-	MONT_MAC(s0, s1, s2, a[6], a[17]);
-	MONT_MAC(c0, c1, c2, a[7], a[16]);
-	MONT_MAC(s0, s1, s2, a[8], a[15]);
-	MONT_MAC(c0, c1, c2, a[9], a[14]);
-	MONT_MAC(s0, s1, s2, a[10], a[13]);
-	MONT_MAC(c0, c1, c2, a[11], a[12]);
-	MONT_MAC(t0, t1, t2, u[0], m[23]);
-	MONT_MUL(v0, v1, v2, u[1], m[22]);
-	MONT_MUL(w0, w1, w2, u[2], m[21]);
-	MONT_MAC(t0, t1, t2, u[3], m[20]);
-	MONT_MAC(v0, v1, v2, u[4], m[19]);
-	MONT_MAC(w0, w1, w2, u[5], m[18]);
-	MONT_MAC(t0, t1, t2, u[6], m[17]);
-	MONT_MAC(v0, v1, v2, u[7], m[16]);
-	MONT_MAC(w0, w1, w2, u[8], m[15]);
-	MONT_MAC(t0, t1, t2, u[9], m[14]);
-	MONT_MAC(v0, v1, v2, u[10], m[13]);
-	MONT_MAC(w0, w1, w2, u[11], m[12]);
-	MONT_MAC(t0, t1, t2, u[12], m[11]);
-	MONT_MAC(v0, v1, v2, u[13], m[10]);
-	MONT_MAC(w0, w1, w2, u[14], m[9]);
-	MONT_MAC(t0, t1, t2, u[15], m[8]);
-	MONT_MAC(v0, v1, v2, u[16], m[7]);
-	MONT_MAC(w0, w1, w2, u[17], m[6]);
-	MONT_MAC(t0, t1, t2, u[18], m[5]);
-	MONT_MAC(v0, v1, v2, u[19], m[4]);
-	MONT_MAC(w0, w1, w2, u[20], m[3]);
-	MONT_MAC(t0, t1, t2, u[21], m[2]);
-	MONT_MAC(v0, v1, v2, u[22], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[23] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[23], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 24 */
-	MONT_MUL(s0, s1, s2, a[0], a[24]);
-	MONT_MUL(c0, c1, c2, a[1], a[23]);
-	MONT_MAC(s0, s1, s2, a[2], a[22]);
-	MONT_MAC(c0, c1, c2, a[3], a[21]);
-	MONT_MAC(s0, s1, s2, a[4], a[20]);
-	MONT_MAC(c0, c1, c2, a[5], a[19]);
-	MONT_MAC(s0, s1, s2, a[6], a[18]);
-	MONT_MAC(c0, c1, c2, a[7], a[17]);
-	MONT_MAC(s0, s1, s2, a[8], a[16]);
-	MONT_MAC(c0, c1, c2, a[9], a[15]);
-	MONT_MAC(s0, s1, s2, a[10], a[14]);
-	MONT_MAC(c0, c1, c2, a[11], a[13]);
-	MONT_MAC(t0, t1, t2, a[12], a[12]);
-	MONT_MUL(v0, v1, v2, u[0], m[24]);
-	MONT_MUL(w0, w1, w2, u[1], m[23]);
-	MONT_MAC(t0, t1, t2, u[2], m[22]);
-	MONT_MAC(v0, v1, v2, u[3], m[21]);
-	MONT_MAC(w0, w1, w2, u[4], m[20]);
-	MONT_MAC(t0, t1, t2, u[5], m[19]);
-	MONT_MAC(v0, v1, v2, u[6], m[18]);
-	MONT_MAC(w0, w1, w2, u[7], m[17]);
-	MONT_MAC(t0, t1, t2, u[8], m[16]);
-	MONT_MAC(v0, v1, v2, u[9], m[15]);
-	MONT_MAC(w0, w1, w2, u[10], m[14]);
-	MONT_MAC(t0, t1, t2, u[11], m[13]);
-	MONT_MAC(v0, v1, v2, u[12], m[12]);
-	MONT_MAC(w0, w1, w2, u[13], m[11]);
-	MONT_MAC(t0, t1, t2, u[14], m[10]);
-	MONT_MAC(v0, v1, v2, u[15], m[9]);
-	MONT_MAC(w0, w1, w2, u[16], m[8]);
-	MONT_MAC(t0, t1, t2, u[17], m[7]);
-	MONT_MAC(v0, v1, v2, u[18], m[6]);
-	MONT_MAC(w0, w1, w2, u[19], m[5]);
-	MONT_MAC(t0, t1, t2, u[20], m[4]);
-	MONT_MAC(v0, v1, v2, u[21], m[3]);
-	MONT_MAC(w0, w1, w2, u[22], m[2]);
-	MONT_MAC(t0, t1, t2, u[23], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[24] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[24], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 25 */
-	MONT_MUL(s0, s1, s2, a[0], a[25]);
-	MONT_MUL(c0, c1, c2, a[1], a[24]);
-	MONT_MAC(s0, s1, s2, a[2], a[23]);
-	MONT_MAC(c0, c1, c2, a[3], a[22]);
-	MONT_MAC(s0, s1, s2, a[4], a[21]);
-	MONT_MAC(c0, c1, c2, a[5], a[20]);
-	MONT_MAC(s0, s1, s2, a[6], a[19]);
-	MONT_MAC(c0, c1, c2, a[7], a[18]);
-	MONT_MAC(s0, s1, s2, a[8], a[17]);
-	MONT_MAC(c0, c1, c2, a[9], a[16]);
-	MONT_MAC(s0, s1, s2, a[10], a[15]);
-	MONT_MAC(c0, c1, c2, a[11], a[14]);
-	MONT_MAC(s0, s1, s2, a[12], a[13]);
-	MONT_MAC(t0, t1, t2, u[0], m[25]);
-	MONT_MUL(v0, v1, v2, u[1], m[24]);
-	MONT_MUL(w0, w1, w2, u[2], m[23]);
-	MONT_MAC(t0, t1, t2, u[3], m[22]);
-	MONT_MAC(v0, v1, v2, u[4], m[21]);
-	MONT_MAC(w0, w1, w2, u[5], m[20]);
-	MONT_MAC(t0, t1, t2, u[6], m[19]);
-	MONT_MAC(v0, v1, v2, u[7], m[18]);
-	MONT_MAC(w0, w1, w2, u[8], m[17]);
-	MONT_MAC(t0, t1, t2, u[9], m[16]);
-	MONT_MAC(v0, v1, v2, u[10], m[15]);
-	MONT_MAC(w0, w1, w2, u[11], m[14]);
-	MONT_MAC(t0, t1, t2, u[12], m[13]);
-	MONT_MAC(v0, v1, v2, u[13], m[12]);
-	MONT_MAC(w0, w1, w2, u[14], m[11]);
-	MONT_MAC(t0, t1, t2, u[15], m[10]);
-	MONT_MAC(v0, v1, v2, u[16], m[9]);
-	MONT_MAC(w0, w1, w2, u[17], m[8]);
-	MONT_MAC(t0, t1, t2, u[18], m[7]);
-	MONT_MAC(v0, v1, v2, u[19], m[6]);
-	MONT_MAC(w0, w1, w2, u[20], m[5]);
-	MONT_MAC(t0, t1, t2, u[21], m[4]);
-	MONT_MAC(v0, v1, v2, u[22], m[3]);
-	MONT_MAC(w0, w1, w2, u[23], m[2]);
-	MONT_MAC(t0, t1, t2, u[24], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[25] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[25], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 26 */
-	MONT_MUL(s0, s1, s2, a[0], a[26]);
-	MONT_MUL(c0, c1, c2, a[1], a[25]);
-	MONT_MAC(s0, s1, s2, a[2], a[24]);
-	MONT_MAC(c0, c1, c2, a[3], a[23]);
-	MONT_MAC(s0, s1, s2, a[4], a[22]);
-	MONT_MAC(c0, c1, c2, a[5], a[21]);
-	MONT_MAC(s0, s1, s2, a[6], a[20]);
-	MONT_MAC(c0, c1, c2, a[7], a[19]);
-	MONT_MAC(s0, s1, s2, a[8], a[18]);
-	MONT_MAC(c0, c1, c2, a[9], a[17]);
-	MONT_MAC(s0, s1, s2, a[10], a[16]);
-	MONT_MAC(c0, c1, c2, a[11], a[15]);
-	MONT_MAC(s0, s1, s2, a[12], a[14]);
-	MONT_MAC(t0, t1, t2, a[13], a[13]);
-	MONT_MUL(v0, v1, v2, u[0], m[26]);
-	MONT_MUL(w0, w1, w2, u[1], m[25]);
-	MONT_MAC(t0, t1, t2, u[2], m[24]);
-	MONT_MAC(v0, v1, v2, u[3], m[23]);
-	MONT_MAC(w0, w1, w2, u[4], m[22]);
-	MONT_MAC(t0, t1, t2, u[5], m[21]);
-	MONT_MAC(v0, v1, v2, u[6], m[20]);
-	MONT_MAC(w0, w1, w2, u[7], m[19]);
-	MONT_MAC(t0, t1, t2, u[8], m[18]);
-	MONT_MAC(v0, v1, v2, u[9], m[17]);
-	MONT_MAC(w0, w1, w2, u[10], m[16]);
-	MONT_MAC(t0, t1, t2, u[11], m[15]);
-	MONT_MAC(v0, v1, v2, u[12], m[14]);
-	MONT_MAC(w0, w1, w2, u[13], m[13]);
-	MONT_MAC(t0, t1, t2, u[14], m[12]);
-	MONT_MAC(v0, v1, v2, u[15], m[11]);
-	MONT_MAC(w0, w1, w2, u[16], m[10]);
-	MONT_MAC(t0, t1, t2, u[17], m[9]);
-	MONT_MAC(v0, v1, v2, u[18], m[8]);
-	MONT_MAC(w0, w1, w2, u[19], m[7]);
-	MONT_MAC(t0, t1, t2, u[20], m[6]);
-	MONT_MAC(v0, v1, v2, u[21], m[5]);
-	MONT_MAC(w0, w1, w2, u[22], m[4]);
-	MONT_MAC(t0, t1, t2, u[23], m[3]);
-	MONT_MAC(v0, v1, v2, u[24], m[2]);
-	MONT_MAC(w0, w1, w2, u[25], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[26] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[26], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 27 */
-	MONT_MUL(s0, s1, s2, a[0], a[27]);
-	MONT_MUL(c0, c1, c2, a[1], a[26]);
-	MONT_MAC(s0, s1, s2, a[2], a[25]);
-	MONT_MAC(c0, c1, c2, a[3], a[24]);
-	MONT_MAC(s0, s1, s2, a[4], a[23]);
-	MONT_MAC(c0, c1, c2, a[5], a[22]);
-	MONT_MAC(s0, s1, s2, a[6], a[21]);
-	MONT_MAC(c0, c1, c2, a[7], a[20]);
-	MONT_MAC(s0, s1, s2, a[8], a[19]);
-	MONT_MAC(c0, c1, c2, a[9], a[18]);
-	MONT_MAC(s0, s1, s2, a[10], a[17]);
-	MONT_MAC(c0, c1, c2, a[11], a[16]);
-	MONT_MAC(s0, s1, s2, a[12], a[15]);
-	MONT_MAC(c0, c1, c2, a[13], a[14]);
-	MONT_MAC(t0, t1, t2, u[0], m[27]);
-	MONT_MUL(v0, v1, v2, u[1], m[26]);
-	MONT_MUL(w0, w1, w2, u[2], m[25]);
-	MONT_MAC(t0, t1, t2, u[3], m[24]);
-	MONT_MAC(v0, v1, v2, u[4], m[23]);
-	MONT_MAC(w0, w1, w2, u[5], m[22]);
-	MONT_MAC(t0, t1, t2, u[6], m[21]);
-	MONT_MAC(v0, v1, v2, u[7], m[20]);
-	MONT_MAC(w0, w1, w2, u[8], m[19]);
-	MONT_MAC(t0, t1, t2, u[9], m[18]);
-	MONT_MAC(v0, v1, v2, u[10], m[17]);
-	MONT_MAC(w0, w1, w2, u[11], m[16]);
-	MONT_MAC(t0, t1, t2, u[12], m[15]);
-	MONT_MAC(v0, v1, v2, u[13], m[14]);
-	MONT_MAC(w0, w1, w2, u[14], m[13]);
-	MONT_MAC(t0, t1, t2, u[15], m[12]);
-	MONT_MAC(v0, v1, v2, u[16], m[11]);
-	MONT_MAC(w0, w1, w2, u[17], m[10]);
-	MONT_MAC(t0, t1, t2, u[18], m[9]);
-	MONT_MAC(v0, v1, v2, u[19], m[8]);
-	MONT_MAC(w0, w1, w2, u[20], m[7]);
-	MONT_MAC(t0, t1, t2, u[21], m[6]);
-	MONT_MAC(v0, v1, v2, u[22], m[5]);
-	MONT_MAC(w0, w1, w2, u[23], m[4]);
-	MONT_MAC(t0, t1, t2, u[24], m[3]);
-	MONT_MAC(v0, v1, v2, u[25], m[2]);
-	MONT_MAC(w0, w1, w2, u[26], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[27] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[27], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 28 */
-	MONT_MUL(s0, s1, s2, a[0], a[28]);
-	MONT_MUL(c0, c1, c2, a[1], a[27]);
-	MONT_MAC(s0, s1, s2, a[2], a[26]);
-	MONT_MAC(c0, c1, c2, a[3], a[25]);
-	MONT_MAC(s0, s1, s2, a[4], a[24]);
-	MONT_MAC(c0, c1, c2, a[5], a[23]);
-	MONT_MAC(s0, s1, s2, a[6], a[22]);
-	MONT_MAC(c0, c1, c2, a[7], a[21]);
-	MONT_MAC(s0, s1, s2, a[8], a[20]);
-	MONT_MAC(c0, c1, c2, a[9], a[19]);
-	MONT_MAC(s0, s1, s2, a[10], a[18]);
-	MONT_MAC(c0, c1, c2, a[11], a[17]);
-	MONT_MAC(s0, s1, s2, a[12], a[16]);
-	MONT_MAC(c0, c1, c2, a[13], a[15]);
-	MONT_MAC(t0, t1, t2, a[14], a[14]);
-	MONT_MUL(v0, v1, v2, u[0], m[28]);
-	MONT_MUL(w0, w1, w2, u[1], m[27]);
-	MONT_MAC(t0, t1, t2, u[2], m[26]);
-	MONT_MAC(v0, v1, v2, u[3], m[25]);
-	MONT_MAC(w0, w1, w2, u[4], m[24]);
-	MONT_MAC(t0, t1, t2, u[5], m[23]);
-	MONT_MAC(v0, v1, v2, u[6], m[22]);
-	MONT_MAC(w0, w1, w2, u[7], m[21]);
-	MONT_MAC(t0, t1, t2, u[8], m[20]);
-	MONT_MAC(v0, v1, v2, u[9], m[19]);
-	MONT_MAC(w0, w1, w2, u[10], m[18]);
-	MONT_MAC(t0, t1, t2, u[11], m[17]);
-	MONT_MAC(v0, v1, v2, u[12], m[16]);
-	MONT_MAC(w0, w1, w2, u[13], m[15]);
-	MONT_MAC(t0, t1, t2, u[14], m[14]);
-	MONT_MAC(v0, v1, v2, u[15], m[13]);
-	MONT_MAC(w0, w1, w2, u[16], m[12]);
-	MONT_MAC(t0, t1, t2, u[17], m[11]);
-	MONT_MAC(v0, v1, v2, u[18], m[10]);
-	MONT_MAC(w0, w1, w2, u[19], m[9]);
-	MONT_MAC(t0, t1, t2, u[20], m[8]);
-	MONT_MAC(v0, v1, v2, u[21], m[7]);
-	MONT_MAC(w0, w1, w2, u[22], m[6]);
-	MONT_MAC(t0, t1, t2, u[23], m[5]);
-	MONT_MAC(v0, v1, v2, u[24], m[4]);
-	MONT_MAC(w0, w1, w2, u[25], m[3]);
-	MONT_MAC(t0, t1, t2, u[26], m[2]);
-	MONT_MAC(v0, v1, v2, u[27], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[28] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[28], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 29 */
-	MONT_MUL(s0, s1, s2, a[0], a[29]);
-	MONT_MUL(c0, c1, c2, a[1], a[28]);
-	MONT_MAC(s0, s1, s2, a[2], a[27]);
-	MONT_MAC(c0, c1, c2, a[3], a[26]);
-	MONT_MAC(s0, s1, s2, a[4], a[25]);
-	MONT_MAC(c0, c1, c2, a[5], a[24]);
-	MONT_MAC(s0, s1, s2, a[6], a[23]);
-	MONT_MAC(c0, c1, c2, a[7], a[22]);
-	MONT_MAC(s0, s1, s2, a[8], a[21]);
-	MONT_MAC(c0, c1, c2, a[9], a[20]);
-	MONT_MAC(s0, s1, s2, a[10], a[19]);
-	MONT_MAC(c0, c1, c2, a[11], a[18]);
-	MONT_MAC(s0, s1, s2, a[12], a[17]);
-	MONT_MAC(c0, c1, c2, a[13], a[16]);
-	MONT_MAC(s0, s1, s2, a[14], a[15]);
-	MONT_MAC(t0, t1, t2, u[0], m[29]);
-	MONT_MUL(v0, v1, v2, u[1], m[28]);
-	MONT_MUL(w0, w1, w2, u[2], m[27]);
-	MONT_MAC(t0, t1, t2, u[3], m[26]);
-	MONT_MAC(v0, v1, v2, u[4], m[25]);
-	MONT_MAC(w0, w1, w2, u[5], m[24]);
-	MONT_MAC(t0, t1, t2, u[6], m[23]);
-	MONT_MAC(v0, v1, v2, u[7], m[22]);
-	MONT_MAC(w0, w1, w2, u[8], m[21]);
-	MONT_MAC(t0, t1, t2, u[9], m[20]);
-	MONT_MAC(v0, v1, v2, u[10], m[19]);
-	MONT_MAC(w0, w1, w2, u[11], m[18]);
-	MONT_MAC(t0, t1, t2, u[12], m[17]);
-	MONT_MAC(v0, v1, v2, u[13], m[16]);
-	MONT_MAC(w0, w1, w2, u[14], m[15]);
-	MONT_MAC(t0, t1, t2, u[15], m[14]);
-	MONT_MAC(v0, v1, v2, u[16], m[13]);
-	MONT_MAC(w0, w1, w2, u[17], m[12]);
-	MONT_MAC(t0, t1, t2, u[18], m[11]);
-	MONT_MAC(v0, v1, v2, u[19], m[10]);
-	MONT_MAC(w0, w1, w2, u[20], m[9]);
-	MONT_MAC(t0, t1, t2, u[21], m[8]);
-	MONT_MAC(v0, v1, v2, u[22], m[7]);
-	MONT_MAC(w0, w1, w2, u[23], m[6]);
-	MONT_MAC(t0, t1, t2, u[24], m[5]);
-	MONT_MAC(v0, v1, v2, u[25], m[4]);
-	MONT_MAC(w0, w1, w2, u[26], m[3]);
-	MONT_MAC(t0, t1, t2, u[27], m[2]);
-	MONT_MAC(v0, v1, v2, u[28], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[29] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[29], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 30 */
-	MONT_MUL(s0, s1, s2, a[0], a[30]);
-	MONT_MUL(c0, c1, c2, a[1], a[29]);
-	MONT_MAC(s0, s1, s2, a[2], a[28]);
-	MONT_MAC(c0, c1, c2, a[3], a[27]);
-	MONT_MAC(s0, s1, s2, a[4], a[26]);
-	MONT_MAC(c0, c1, c2, a[5], a[25]);
-	MONT_MAC(s0, s1, s2, a[6], a[24]);
-	MONT_MAC(c0, c1, c2, a[7], a[23]);
-	MONT_MAC(s0, s1, s2, a[8], a[22]);
-	MONT_MAC(c0, c1, c2, a[9], a[21]);
-	MONT_MAC(s0, s1, s2, a[10], a[20]);
-	MONT_MAC(c0, c1, c2, a[11], a[19]);
-	MONT_MAC(s0, s1, s2, a[12], a[18]);
-	MONT_MAC(c0, c1, c2, a[13], a[17]);
-	MONT_MAC(s0, s1, s2, a[14], a[16]);
-	MONT_MAC(t0, t1, t2, a[15], a[15]);
-	MONT_MUL(v0, v1, v2, u[0], m[30]);
-	MONT_MUL(w0, w1, w2, u[1], m[29]);
-	MONT_MAC(t0, t1, t2, u[2], m[28]);
-	MONT_MAC(v0, v1, v2, u[3], m[27]);
-	MONT_MAC(w0, w1, w2, u[4], m[26]);
-	MONT_MAC(t0, t1, t2, u[5], m[25]);
-	MONT_MAC(v0, v1, v2, u[6], m[24]);
-	MONT_MAC(w0, w1, w2, u[7], m[23]);
-	MONT_MAC(t0, t1, t2, u[8], m[22]);
-	MONT_MAC(v0, v1, v2, u[9], m[21]);
-	MONT_MAC(w0, w1, w2, u[10], m[20]);
-	MONT_MAC(t0, t1, t2, u[11], m[19]);
-	MONT_MAC(v0, v1, v2, u[12], m[18]);
-	MONT_MAC(w0, w1, w2, u[13], m[17]);
-	MONT_MAC(t0, t1, t2, u[14], m[16]);
-	MONT_MAC(v0, v1, v2, u[15], m[15]);
-	MONT_MAC(w0, w1, w2, u[16], m[14]);
-	MONT_MAC(t0, t1, t2, u[17], m[13]);
-	MONT_MAC(v0, v1, v2, u[18], m[12]);
-	MONT_MAC(w0, w1, w2, u[19], m[11]);
-	MONT_MAC(t0, t1, t2, u[20], m[10]);
-	MONT_MAC(v0, v1, v2, u[21], m[9]);
-	MONT_MAC(w0, w1, w2, u[22], m[8]);
-	MONT_MAC(t0, t1, t2, u[23], m[7]);
-	MONT_MAC(v0, v1, v2, u[24], m[6]);
-	MONT_MAC(w0, w1, w2, u[25], m[5]);
-	MONT_MAC(t0, t1, t2, u[26], m[4]);
-	MONT_MAC(v0, v1, v2, u[27], m[3]);
-	MONT_MAC(w0, w1, w2, u[28], m[2]);
-	MONT_MAC(t0, t1, t2, u[29], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[30] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[30], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 31 */
-	MONT_MUL(s0, s1, s2, a[0], a[31]);
-	MONT_MUL(c0, c1, c2, a[1], a[30]);
-	MONT_MAC(s0, s1, s2, a[2], a[29]);
-	MONT_MAC(c0, c1, c2, a[3], a[28]);
-	MONT_MAC(s0, s1, s2, a[4], a[27]);
-	MONT_MAC(c0, c1, c2, a[5], a[26]);
-	MONT_MAC(s0, s1, s2, a[6], a[25]);
-	MONT_MAC(c0, c1, c2, a[7], a[24]);
-	MONT_MAC(s0, s1, s2, a[8], a[23]);
-	MONT_MAC(c0, c1, c2, a[9], a[22]);
-	MONT_MAC(s0, s1, s2, a[10], a[21]);
-	MONT_MAC(c0, c1, c2, a[11], a[20]);
-	MONT_MAC(s0, s1, s2, a[12], a[19]);
-	MONT_MAC(c0, c1, c2, a[13], a[18]);
-	MONT_MAC(s0, s1, s2, a[14], a[17]);
-	MONT_MAC(c0, c1, c2, a[15], a[16]);
-	MONT_MAC(t0, t1, t2, u[0], m[31]);
-	MONT_MUL(v0, v1, v2, u[1], m[30]);
-	MONT_MUL(w0, w1, w2, u[2], m[29]);
-	MONT_MAC(t0, t1, t2, u[3], m[28]);
-	MONT_MAC(v0, v1, v2, u[4], m[27]);
-	MONT_MAC(w0, w1, w2, u[5], m[26]);
-	MONT_MAC(t0, t1, t2, u[6], m[25]);
-	MONT_MAC(v0, v1, v2, u[7], m[24]);
-	MONT_MAC(w0, w1, w2, u[8], m[23]);
-	MONT_MAC(t0, t1, t2, u[9], m[22]);
-	MONT_MAC(v0, v1, v2, u[10], m[21]);
-	MONT_MAC(w0, w1, w2, u[11], m[20]);
-	MONT_MAC(t0, t1, t2, u[12], m[19]);
-	MONT_MAC(v0, v1, v2, u[13], m[18]);
-	MONT_MAC(w0, w1, w2, u[14], m[17]);
-	MONT_MAC(t0, t1, t2, u[15], m[16]);
-	MONT_MAC(v0, v1, v2, u[16], m[15]);
-	MONT_MAC(w0, w1, w2, u[17], m[14]);
-	MONT_MAC(t0, t1, t2, u[18], m[13]);
-	MONT_MAC(v0, v1, v2, u[19], m[12]);
-	MONT_MAC(w0, w1, w2, u[20], m[11]);
-	MONT_MAC(t0, t1, t2, u[21], m[10]);
-	MONT_MAC(v0, v1, v2, u[22], m[9]);
-	MONT_MAC(w0, w1, w2, u[23], m[8]);
-	MONT_MAC(t0, t1, t2, u[24], m[7]);
-	MONT_MAC(v0, v1, v2, u[25], m[6]);
-	MONT_MAC(w0, w1, w2, u[26], m[5]);
-	MONT_MAC(t0, t1, t2, u[27], m[4]);
-	MONT_MAC(v0, v1, v2, u[28], m[3]);
-	MONT_MAC(w0, w1, w2, u[29], m[2]);
-	MONT_MAC(t0, t1, t2, u[30], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	u[31] = t0 * n0;
-	MONT_MAC(t0, t1, t2, u[31], m[0]);
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 32 */
-	MONT_MUL(s0, s1, s2, a[1], a[31]);
-	MONT_MUL(c0, c1, c2, a[2], a[30]);
-	MONT_MAC(s0, s1, s2, a[3], a[29]);
-	MONT_MAC(c0, c1, c2, a[4], a[28]);
-	MONT_MAC(s0, s1, s2, a[5], a[27]);
-	MONT_MAC(c0, c1, c2, a[6], a[26]);
-	MONT_MAC(s0, s1, s2, a[7], a[25]);
-	MONT_MAC(c0, c1, c2, a[8], a[24]);
-	MONT_MAC(s0, s1, s2, a[9], a[23]);
-	MONT_MAC(c0, c1, c2, a[10], a[22]);
-	MONT_MAC(s0, s1, s2, a[11], a[21]);
-	MONT_MAC(c0, c1, c2, a[12], a[20]);
-	MONT_MAC(s0, s1, s2, a[13], a[19]);
-	MONT_MAC(c0, c1, c2, a[14], a[18]);
-	MONT_MAC(s0, s1, s2, a[15], a[17]);
-	MONT_MAC(t0, t1, t2, a[16], a[16]);
-	MONT_MUL(v0, v1, v2, u[1], m[31]);
-	MONT_MUL(w0, w1, w2, u[2], m[30]);
-	MONT_MAC(t0, t1, t2, u[3], m[29]);
-	MONT_MAC(v0, v1, v2, u[4], m[28]);
-	MONT_MAC(w0, w1, w2, u[5], m[27]);
-	MONT_MAC(t0, t1, t2, u[6], m[26]);
-	MONT_MAC(v0, v1, v2, u[7], m[25]);
-	MONT_MAC(w0, w1, w2, u[8], m[24]);
-	MONT_MAC(t0, t1, t2, u[9], m[23]);
-	MONT_MAC(v0, v1, v2, u[10], m[22]);
-	MONT_MAC(w0, w1, w2, u[11], m[21]);
-	MONT_MAC(t0, t1, t2, u[12], m[20]);
-	MONT_MAC(v0, v1, v2, u[13], m[19]);
-	MONT_MAC(w0, w1, w2, u[14], m[18]);
-	MONT_MAC(t0, t1, t2, u[15], m[17]);
-	MONT_MAC(v0, v1, v2, u[16], m[16]);
-	MONT_MAC(w0, w1, w2, u[17], m[15]);
-	MONT_MAC(t0, t1, t2, u[18], m[14]);
-	MONT_MAC(v0, v1, v2, u[19], m[13]);
-	MONT_MAC(w0, w1, w2, u[20], m[12]);
-	MONT_MAC(t0, t1, t2, u[21], m[11]);
-	MONT_MAC(v0, v1, v2, u[22], m[10]);
-	MONT_MAC(w0, w1, w2, u[23], m[9]);
-	MONT_MAC(t0, t1, t2, u[24], m[8]);
-	MONT_MAC(v0, v1, v2, u[25], m[7]);
-	MONT_MAC(w0, w1, w2, u[26], m[6]);
-	MONT_MAC(t0, t1, t2, u[27], m[5]);
-	MONT_MAC(v0, v1, v2, u[28], m[4]);
-	MONT_MAC(w0, w1, w2, u[29], m[3]);
-	MONT_MAC(t0, t1, t2, u[30], m[2]);
-	MONT_MAC(v0, v1, v2, u[31], m[1]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[0] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 33 */
-	MONT_MUL(s0, s1, s2, a[2], a[31]);
-	MONT_MUL(c0, c1, c2, a[3], a[30]);
-	MONT_MAC(s0, s1, s2, a[4], a[29]);
-	MONT_MAC(c0, c1, c2, a[5], a[28]);
-	MONT_MAC(s0, s1, s2, a[6], a[27]);
-	MONT_MAC(c0, c1, c2, a[7], a[26]);
-	MONT_MAC(s0, s1, s2, a[8], a[25]);
-	MONT_MAC(c0, c1, c2, a[9], a[24]);
-	MONT_MAC(s0, s1, s2, a[10], a[23]);
-	MONT_MAC(c0, c1, c2, a[11], a[22]);
-	MONT_MAC(s0, s1, s2, a[12], a[21]);
-	MONT_MAC(c0, c1, c2, a[13], a[20]);
-	MONT_MAC(s0, s1, s2, a[14], a[19]);
-	MONT_MAC(c0, c1, c2, a[15], a[18]);
-	MONT_MAC(s0, s1, s2, a[16], a[17]);
-	MONT_MAC(t0, t1, t2, u[2], m[31]);
-	MONT_MUL(v0, v1, v2, u[3], m[30]);
-	MONT_MUL(w0, w1, w2, u[4], m[29]);
-	MONT_MAC(t0, t1, t2, u[5], m[28]);
-	MONT_MAC(v0, v1, v2, u[6], m[27]);
-	MONT_MAC(w0, w1, w2, u[7], m[26]);
-	MONT_MAC(t0, t1, t2, u[8], m[25]);
-	MONT_MAC(v0, v1, v2, u[9], m[24]);
-	MONT_MAC(w0, w1, w2, u[10], m[23]);
-	MONT_MAC(t0, t1, t2, u[11], m[22]);
-	MONT_MAC(v0, v1, v2, u[12], m[21]);
-	MONT_MAC(w0, w1, w2, u[13], m[20]);
-	MONT_MAC(t0, t1, t2, u[14], m[19]);
-	MONT_MAC(v0, v1, v2, u[15], m[18]);
-	MONT_MAC(w0, w1, w2, u[16], m[17]);
-	MONT_MAC(t0, t1, t2, u[17], m[16]);
-	MONT_MAC(v0, v1, v2, u[18], m[15]);
-	MONT_MAC(w0, w1, w2, u[19], m[14]);
-	MONT_MAC(t0, t1, t2, u[20], m[13]);
-	MONT_MAC(v0, v1, v2, u[21], m[12]);
-	MONT_MAC(w0, w1, w2, u[22], m[11]);
-	MONT_MAC(t0, t1, t2, u[23], m[10]);
-	MONT_MAC(v0, v1, v2, u[24], m[9]);
-	MONT_MAC(w0, w1, w2, u[25], m[8]);
-	MONT_MAC(t0, t1, t2, u[26], m[7]);
-	MONT_MAC(v0, v1, v2, u[27], m[6]);
-	MONT_MAC(w0, w1, w2, u[28], m[5]);
-	MONT_MAC(t0, t1, t2, u[29], m[4]);
-	MONT_MAC(v0, v1, v2, u[30], m[3]);
-	MONT_MAC(w0, w1, w2, u[31], m[2]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[1] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 34 */
-	MONT_MUL(s0, s1, s2, a[3], a[31]);
-	MONT_MUL(c0, c1, c2, a[4], a[30]);
-	MONT_MAC(s0, s1, s2, a[5], a[29]);
-	MONT_MAC(c0, c1, c2, a[6], a[28]);
-	MONT_MAC(s0, s1, s2, a[7], a[27]);
-	MONT_MAC(c0, c1, c2, a[8], a[26]);
-	MONT_MAC(s0, s1, s2, a[9], a[25]);
-	MONT_MAC(c0, c1, c2, a[10], a[24]);
-	MONT_MAC(s0, s1, s2, a[11], a[23]);
-	MONT_MAC(c0, c1, c2, a[12], a[22]);
-	MONT_MAC(s0, s1, s2, a[13], a[21]);
-	MONT_MAC(c0, c1, c2, a[14], a[20]);
-	MONT_MAC(s0, s1, s2, a[15], a[19]);
-	MONT_MAC(c0, c1, c2, a[16], a[18]);
-	MONT_MAC(t0, t1, t2, a[17], a[17]);
-	MONT_MUL(v0, v1, v2, u[3], m[31]);
-	MONT_MUL(w0, w1, w2, u[4], m[30]);
-	MONT_MAC(t0, t1, t2, u[5], m[29]);
-	MONT_MAC(v0, v1, v2, u[6], m[28]);
-	MONT_MAC(w0, w1, w2, u[7], m[27]);
-	MONT_MAC(t0, t1, t2, u[8], m[26]);
-	MONT_MAC(v0, v1, v2, u[9], m[25]);
-	MONT_MAC(w0, w1, w2, u[10], m[24]);
-	MONT_MAC(t0, t1, t2, u[11], m[23]);
-	MONT_MAC(v0, v1, v2, u[12], m[22]);
-	MONT_MAC(w0, w1, w2, u[13], m[21]);
-	MONT_MAC(t0, t1, t2, u[14], m[20]);
-	MONT_MAC(v0, v1, v2, u[15], m[19]);
-	MONT_MAC(w0, w1, w2, u[16], m[18]);
-	MONT_MAC(t0, t1, t2, u[17], m[17]);
-	MONT_MAC(v0, v1, v2, u[18], m[16]);
-	MONT_MAC(w0, w1, w2, u[19], m[15]);
-	MONT_MAC(t0, t1, t2, u[20], m[14]);
-	MONT_MAC(v0, v1, v2, u[21], m[13]);
-	MONT_MAC(w0, w1, w2, u[22], m[12]);
-	MONT_MAC(t0, t1, t2, u[23], m[11]);
-	MONT_MAC(v0, v1, v2, u[24], m[10]);
-	MONT_MAC(w0, w1, w2, u[25], m[9]);
-	MONT_MAC(t0, t1, t2, u[26], m[8]);
-	MONT_MAC(v0, v1, v2, u[27], m[7]);
-	MONT_MAC(w0, w1, w2, u[28], m[6]);
-	MONT_MAC(t0, t1, t2, u[29], m[5]);
-	MONT_MAC(v0, v1, v2, u[30], m[4]);
-	MONT_MAC(w0, w1, w2, u[31], m[3]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[2] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 35 */
-	MONT_MUL(s0, s1, s2, a[4], a[31]);
-	MONT_MUL(c0, c1, c2, a[5], a[30]);
-	MONT_MAC(s0, s1, s2, a[6], a[29]);
-	MONT_MAC(c0, c1, c2, a[7], a[28]);
-	MONT_MAC(s0, s1, s2, a[8], a[27]);
-	MONT_MAC(c0, c1, c2, a[9], a[26]);
-	MONT_MAC(s0, s1, s2, a[10], a[25]);
-	MONT_MAC(c0, c1, c2, a[11], a[24]);
-	MONT_MAC(s0, s1, s2, a[12], a[23]);
-	MONT_MAC(c0, c1, c2, a[13], a[22]);
-	MONT_MAC(s0, s1, s2, a[14], a[21]);
-	MONT_MAC(c0, c1, c2, a[15], a[20]);
-	MONT_MAC(s0, s1, s2, a[16], a[19]);
-	MONT_MAC(c0, c1, c2, a[17], a[18]);
-	MONT_MAC(t0, t1, t2, u[4], m[31]);
-	MONT_MUL(v0, v1, v2, u[5], m[30]);
-	MONT_MUL(w0, w1, w2, u[6], m[29]);
-	MONT_MAC(t0, t1, t2, u[7], m[28]);
-	MONT_MAC(v0, v1, v2, u[8], m[27]);
-	MONT_MAC(w0, w1, w2, u[9], m[26]);
-	MONT_MAC(t0, t1, t2, u[10], m[25]);
-	MONT_MAC(v0, v1, v2, u[11], m[24]);
-	MONT_MAC(w0, w1, w2, u[12], m[23]);
-	MONT_MAC(t0, t1, t2, u[13], m[22]);
-	MONT_MAC(v0, v1, v2, u[14], m[21]);
-	MONT_MAC(w0, w1, w2, u[15], m[20]);
-	MONT_MAC(t0, t1, t2, u[16], m[19]);
-	MONT_MAC(v0, v1, v2, u[17], m[18]);
-	MONT_MAC(w0, w1, w2, u[18], m[17]);
-	MONT_MAC(t0, t1, t2, u[19], m[16]);
-	MONT_MAC(v0, v1, v2, u[20], m[15]);
-	MONT_MAC(w0, w1, w2, u[21], m[14]);
-	MONT_MAC(t0, t1, t2, u[22], m[13]);
-	MONT_MAC(v0, v1, v2, u[23], m[12]);
-	MONT_MAC(w0, w1, w2, u[24], m[11]);
-	MONT_MAC(t0, t1, t2, u[25], m[10]);
-	MONT_MAC(v0, v1, v2, u[26], m[9]);
-	MONT_MAC(w0, w1, w2, u[27], m[8]);
-	MONT_MAC(t0, t1, t2, u[28], m[7]);
-	MONT_MAC(v0, v1, v2, u[29], m[6]);
-	MONT_MAC(w0, w1, w2, u[30], m[5]);
-	MONT_MAC(t0, t1, t2, u[31], m[4]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[3] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 36 */
-	MONT_MUL(s0, s1, s2, a[5], a[31]);
-	MONT_MUL(c0, c1, c2, a[6], a[30]);
-	MONT_MAC(s0, s1, s2, a[7], a[29]);
-	MONT_MAC(c0, c1, c2, a[8], a[28]);
-	MONT_MAC(s0, s1, s2, a[9], a[27]);
-	MONT_MAC(c0, c1, c2, a[10], a[26]);
-	MONT_MAC(s0, s1, s2, a[11], a[25]);
-	MONT_MAC(c0, c1, c2, a[12], a[24]);
-	MONT_MAC(s0, s1, s2, a[13], a[23]);
-	MONT_MAC(c0, c1, c2, a[14], a[22]);
-	MONT_MAC(s0, s1, s2, a[15], a[21]);
-	MONT_MAC(c0, c1, c2, a[16], a[20]);
-	MONT_MAC(s0, s1, s2, a[17], a[19]);
-	MONT_MAC(t0, t1, t2, a[18], a[18]);
-	MONT_MUL(v0, v1, v2, u[5], m[31]);
-	MONT_MUL(w0, w1, w2, u[6], m[30]);
-	MONT_MAC(t0, t1, t2, u[7], m[29]);
-	MONT_MAC(v0, v1, v2, u[8], m[28]);
-	MONT_MAC(w0, w1, w2, u[9], m[27]);
-	MONT_MAC(t0, t1, t2, u[10], m[26]);
-	MONT_MAC(v0, v1, v2, u[11], m[25]);
-	MONT_MAC(w0, w1, w2, u[12], m[24]);
-	MONT_MAC(t0, t1, t2, u[13], m[23]);
-	MONT_MAC(v0, v1, v2, u[14], m[22]);
-	MONT_MAC(w0, w1, w2, u[15], m[21]);
-	MONT_MAC(t0, t1, t2, u[16], m[20]);
-	MONT_MAC(v0, v1, v2, u[17], m[19]);
-	MONT_MAC(w0, w1, w2, u[18], m[18]);
-	MONT_MAC(t0, t1, t2, u[19], m[17]);
-	MONT_MAC(v0, v1, v2, u[20], m[16]);
-	MONT_MAC(w0, w1, w2, u[21], m[15]);
-	MONT_MAC(t0, t1, t2, u[22], m[14]);
-	MONT_MAC(v0, v1, v2, u[23], m[13]);
-	MONT_MAC(w0, w1, w2, u[24], m[12]);
-	MONT_MAC(t0, t1, t2, u[25], m[11]);
-	MONT_MAC(v0, v1, v2, u[26], m[10]);
-	MONT_MAC(w0, w1, w2, u[27], m[9]);
-	MONT_MAC(t0, t1, t2, u[28], m[8]);
-	MONT_MAC(v0, v1, v2, u[29], m[7]);
-	MONT_MAC(w0, w1, w2, u[30], m[6]);
-	MONT_MAC(t0, t1, t2, u[31], m[5]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[4] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 37 */
-	MONT_MUL(s0, s1, s2, a[6], a[31]);
-	MONT_MUL(c0, c1, c2, a[7], a[30]);
-	MONT_MAC(s0, s1, s2, a[8], a[29]);
-	MONT_MAC(c0, c1, c2, a[9], a[28]);
-	MONT_MAC(s0, s1, s2, a[10], a[27]);
-	MONT_MAC(c0, c1, c2, a[11], a[26]);
-	MONT_MAC(s0, s1, s2, a[12], a[25]);
-	MONT_MAC(c0, c1, c2, a[13], a[24]);
-	MONT_MAC(s0, s1, s2, a[14], a[23]);
-	MONT_MAC(c0, c1, c2, a[15], a[22]);
-	MONT_MAC(s0, s1, s2, a[16], a[21]);
-	MONT_MAC(c0, c1, c2, a[17], a[20]);
-	MONT_MAC(s0, s1, s2, a[18], a[19]);
-	MONT_MAC(t0, t1, t2, u[6], m[31]);
-	MONT_MUL(v0, v1, v2, u[7], m[30]);
-	MONT_MUL(w0, w1, w2, u[8], m[29]);
-	MONT_MAC(t0, t1, t2, u[9], m[28]);
-	MONT_MAC(v0, v1, v2, u[10], m[27]);
-	MONT_MAC(w0, w1, w2, u[11], m[26]);
-	MONT_MAC(t0, t1, t2, u[12], m[25]);
-	MONT_MAC(v0, v1, v2, u[13], m[24]);
-	MONT_MAC(w0, w1, w2, u[14], m[23]);
-	MONT_MAC(t0, t1, t2, u[15], m[22]);
-	MONT_MAC(v0, v1, v2, u[16], m[21]);
-	MONT_MAC(w0, w1, w2, u[17], m[20]);
-	MONT_MAC(t0, t1, t2, u[18], m[19]);
-	MONT_MAC(v0, v1, v2, u[19], m[18]);
-	MONT_MAC(w0, w1, w2, u[20], m[17]);
-	MONT_MAC(t0, t1, t2, u[21], m[16]);
-	MONT_MAC(v0, v1, v2, u[22], m[15]);
-	MONT_MAC(w0, w1, w2, u[23], m[14]);
-	MONT_MAC(t0, t1, t2, u[24], m[13]);
-	MONT_MAC(v0, v1, v2, u[25], m[12]);
-	MONT_MAC(w0, w1, w2, u[26], m[11]);
-	MONT_MAC(t0, t1, t2, u[27], m[10]);
-	MONT_MAC(v0, v1, v2, u[28], m[9]);
-	MONT_MAC(w0, w1, w2, u[29], m[8]);
-	MONT_MAC(t0, t1, t2, u[30], m[7]);
-	MONT_MAC(v0, v1, v2, u[31], m[6]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[5] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 38 */
-	MONT_MUL(s0, s1, s2, a[7], a[31]);
-	MONT_MUL(c0, c1, c2, a[8], a[30]);
-	MONT_MAC(s0, s1, s2, a[9], a[29]);
-	MONT_MAC(c0, c1, c2, a[10], a[28]);
-	MONT_MAC(s0, s1, s2, a[11], a[27]);
-	MONT_MAC(c0, c1, c2, a[12], a[26]);
-	MONT_MAC(s0, s1, s2, a[13], a[25]);
-	MONT_MAC(c0, c1, c2, a[14], a[24]);
-	MONT_MAC(s0, s1, s2, a[15], a[23]);
-	MONT_MAC(c0, c1, c2, a[16], a[22]);
-	MONT_MAC(s0, s1, s2, a[17], a[21]);
-	MONT_MAC(c0, c1, c2, a[18], a[20]);
-	MONT_MAC(t0, t1, t2, a[19], a[19]);
-	MONT_MUL(v0, v1, v2, u[7], m[31]);
-	MONT_MUL(w0, w1, w2, u[8], m[30]);
-	MONT_MAC(t0, t1, t2, u[9], m[29]);
-	MONT_MAC(v0, v1, v2, u[10], m[28]);
-	MONT_MAC(w0, w1, w2, u[11], m[27]);
-	MONT_MAC(t0, t1, t2, u[12], m[26]);
-	MONT_MAC(v0, v1, v2, u[13], m[25]);
-	MONT_MAC(w0, w1, w2, u[14], m[24]);
-	MONT_MAC(t0, t1, t2, u[15], m[23]);
-	MONT_MAC(v0, v1, v2, u[16], m[22]);
-	MONT_MAC(w0, w1, w2, u[17], m[21]);
-	MONT_MAC(t0, t1, t2, u[18], m[20]);
-	MONT_MAC(v0, v1, v2, u[19], m[19]);
-	MONT_MAC(w0, w1, w2, u[20], m[18]);
-	MONT_MAC(t0, t1, t2, u[21], m[17]);
-	MONT_MAC(v0, v1, v2, u[22], m[16]);
-	MONT_MAC(w0, w1, w2, u[23], m[15]);
-	MONT_MAC(t0, t1, t2, u[24], m[14]);
-	MONT_MAC(v0, v1, v2, u[25], m[13]);
-	MONT_MAC(w0, w1, w2, u[26], m[12]);
-	MONT_MAC(t0, t1, t2, u[27], m[11]);
-	MONT_MAC(v0, v1, v2, u[28], m[10]);
-	MONT_MAC(w0, w1, w2, u[29], m[9]);
-	MONT_MAC(t0, t1, t2, u[30], m[8]);
-	MONT_MAC(v0, v1, v2, u[31], m[7]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[6] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 39 */
-	MONT_MUL(s0, s1, s2, a[8], a[31]);
-	MONT_MUL(c0, c1, c2, a[9], a[30]);
-	MONT_MAC(s0, s1, s2, a[10], a[29]);
-	MONT_MAC(c0, c1, c2, a[11], a[28]);
-	MONT_MAC(s0, s1, s2, a[12], a[27]);
-	MONT_MAC(c0, c1, c2, a[13], a[26]);
-	MONT_MAC(s0, s1, s2, a[14], a[25]);
-	MONT_MAC(c0, c1, c2, a[15], a[24]);
-	MONT_MAC(s0, s1, s2, a[16], a[23]);
-	MONT_MAC(c0, c1, c2, a[17], a[22]);
-	MONT_MAC(s0, s1, s2, a[18], a[21]);
-	MONT_MAC(c0, c1, c2, a[19], a[20]);
-	MONT_MAC(t0, t1, t2, u[8], m[31]);
-	MONT_MUL(v0, v1, v2, u[9], m[30]);
-	MONT_MUL(w0, w1, w2, u[10], m[29]);
-	MONT_MAC(t0, t1, t2, u[11], m[28]);
-	MONT_MAC(v0, v1, v2, u[12], m[27]);
-	MONT_MAC(w0, w1, w2, u[13], m[26]);
-	MONT_MAC(t0, t1, t2, u[14], m[25]);
-	MONT_MAC(v0, v1, v2, u[15], m[24]);
-	MONT_MAC(w0, w1, w2, u[16], m[23]);
-	MONT_MAC(t0, t1, t2, u[17], m[22]);
-	MONT_MAC(v0, v1, v2, u[18], m[21]);
-	MONT_MAC(w0, w1, w2, u[19], m[20]);
-	MONT_MAC(t0, t1, t2, u[20], m[19]);
-	MONT_MAC(v0, v1, v2, u[21], m[18]);
-	MONT_MAC(w0, w1, w2, u[22], m[17]);
-	MONT_MAC(t0, t1, t2, u[23], m[16]);
-	MONT_MAC(v0, v1, v2, u[24], m[15]);
-	MONT_MAC(w0, w1, w2, u[25], m[14]);
-	MONT_MAC(t0, t1, t2, u[26], m[13]);
-	MONT_MAC(v0, v1, v2, u[27], m[12]);
-	MONT_MAC(w0, w1, w2, u[28], m[11]);
-	MONT_MAC(t0, t1, t2, u[29], m[10]);
-	MONT_MAC(v0, v1, v2, u[30], m[9]);
-	MONT_MAC(w0, w1, w2, u[31], m[8]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[7] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 40 */
-	MONT_MUL(s0, s1, s2, a[9], a[31]);
-	MONT_MUL(c0, c1, c2, a[10], a[30]);
-	MONT_MAC(s0, s1, s2, a[11], a[29]);
-	MONT_MAC(c0, c1, c2, a[12], a[28]);
-	MONT_MAC(s0, s1, s2, a[13], a[27]);
-	MONT_MAC(c0, c1, c2, a[14], a[26]);
-	MONT_MAC(s0, s1, s2, a[15], a[25]);
-	MONT_MAC(c0, c1, c2, a[16], a[24]);
-	MONT_MAC(s0, s1, s2, a[17], a[23]);
-	MONT_MAC(c0, c1, c2, a[18], a[22]);
-	MONT_MAC(s0, s1, s2, a[19], a[21]);
-	MONT_MAC(t0, t1, t2, a[20], a[20]);
-	MONT_MUL(v0, v1, v2, u[9], m[31]);
-	MONT_MUL(w0, w1, w2, u[10], m[30]);
-	MONT_MAC(t0, t1, t2, u[11], m[29]);
-	MONT_MAC(v0, v1, v2, u[12], m[28]);
-	MONT_MAC(w0, w1, w2, u[13], m[27]);
-	MONT_MAC(t0, t1, t2, u[14], m[26]);
-	MONT_MAC(v0, v1, v2, u[15], m[25]);
-	MONT_MAC(w0, w1, w2, u[16], m[24]);
-	MONT_MAC(t0, t1, t2, u[17], m[23]);
-	MONT_MAC(v0, v1, v2, u[18], m[22]);
-	MONT_MAC(w0, w1, w2, u[19], m[21]);
-	MONT_MAC(t0, t1, t2, u[20], m[20]);
-	MONT_MAC(v0, v1, v2, u[21], m[19]);
-	MONT_MAC(w0, w1, w2, u[22], m[18]);
-	MONT_MAC(t0, t1, t2, u[23], m[17]);
-	MONT_MAC(v0, v1, v2, u[24], m[16]);
-	MONT_MAC(w0, w1, w2, u[25], m[15]);
-	MONT_MAC(t0, t1, t2, u[26], m[14]);
-	MONT_MAC(v0, v1, v2, u[27], m[13]);
-	MONT_MAC(w0, w1, w2, u[28], m[12]);
-	MONT_MAC(t0, t1, t2, u[29], m[11]);
-	MONT_MAC(v0, v1, v2, u[30], m[10]);
-	MONT_MAC(w0, w1, w2, u[31], m[9]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[8] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 41 */
-	MONT_MUL(s0, s1, s2, a[10], a[31]);
-	MONT_MUL(c0, c1, c2, a[11], a[30]);
-	MONT_MAC(s0, s1, s2, a[12], a[29]);
-	MONT_MAC(c0, c1, c2, a[13], a[28]);
-	MONT_MAC(s0, s1, s2, a[14], a[27]);
-	MONT_MAC(c0, c1, c2, a[15], a[26]);
-	MONT_MAC(s0, s1, s2, a[16], a[25]);
-	MONT_MAC(c0, c1, c2, a[17], a[24]);
-	MONT_MAC(s0, s1, s2, a[18], a[23]);
-	MONT_MAC(c0, c1, c2, a[19], a[22]);
-	MONT_MAC(s0, s1, s2, a[20], a[21]);
-	MONT_MAC(t0, t1, t2, u[10], m[31]);
-	MONT_MUL(v0, v1, v2, u[11], m[30]);
-	MONT_MUL(w0, w1, w2, u[12], m[29]);
-	MONT_MAC(t0, t1, t2, u[13], m[28]);
-	MONT_MAC(v0, v1, v2, u[14], m[27]);
-	MONT_MAC(w0, w1, w2, u[15], m[26]);
-	MONT_MAC(t0, t1, t2, u[16], m[25]);
-	MONT_MAC(v0, v1, v2, u[17], m[24]);
-	MONT_MAC(w0, w1, w2, u[18], m[23]);
-	MONT_MAC(t0, t1, t2, u[19], m[22]);
-	MONT_MAC(v0, v1, v2, u[20], m[21]);
-	MONT_MAC(w0, w1, w2, u[21], m[20]);
-	MONT_MAC(t0, t1, t2, u[22], m[19]);
-	MONT_MAC(v0, v1, v2, u[23], m[18]);
-	MONT_MAC(w0, w1, w2, u[24], m[17]);
-	MONT_MAC(t0, t1, t2, u[25], m[16]);
-	MONT_MAC(v0, v1, v2, u[26], m[15]);
-	MONT_MAC(w0, w1, w2, u[27], m[14]);
-	MONT_MAC(t0, t1, t2, u[28], m[13]);
-	MONT_MAC(v0, v1, v2, u[29], m[12]);
-	MONT_MAC(w0, w1, w2, u[30], m[11]);
-	MONT_MAC(t0, t1, t2, u[31], m[10]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[9] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 42 */
-	MONT_MUL(s0, s1, s2, a[11], a[31]);
-	MONT_MUL(c0, c1, c2, a[12], a[30]);
-	MONT_MAC(s0, s1, s2, a[13], a[29]);
-	MONT_MAC(c0, c1, c2, a[14], a[28]);
-	MONT_MAC(s0, s1, s2, a[15], a[27]);
-	MONT_MAC(c0, c1, c2, a[16], a[26]);
-	MONT_MAC(s0, s1, s2, a[17], a[25]);
-	MONT_MAC(c0, c1, c2, a[18], a[24]);
-	MONT_MAC(s0, s1, s2, a[19], a[23]);
-	MONT_MAC(c0, c1, c2, a[20], a[22]);
-	MONT_MAC(t0, t1, t2, a[21], a[21]);
-	MONT_MUL(v0, v1, v2, u[11], m[31]);
-	MONT_MUL(w0, w1, w2, u[12], m[30]);
-	MONT_MAC(t0, t1, t2, u[13], m[29]);
-	MONT_MAC(v0, v1, v2, u[14], m[28]);
-	MONT_MAC(w0, w1, w2, u[15], m[27]);
-	MONT_MAC(t0, t1, t2, u[16], m[26]);
-	MONT_MAC(v0, v1, v2, u[17], m[25]);
-	MONT_MAC(w0, w1, w2, u[18], m[24]);
-	MONT_MAC(t0, t1, t2, u[19], m[23]);
-	MONT_MAC(v0, v1, v2, u[20], m[22]);
-	MONT_MAC(w0, w1, w2, u[21], m[21]);
-	MONT_MAC(t0, t1, t2, u[22], m[20]);
-	MONT_MAC(v0, v1, v2, u[23], m[19]);
-	MONT_MAC(w0, w1, w2, u[24], m[18]);
-	MONT_MAC(t0, t1, t2, u[25], m[17]);
-	MONT_MAC(v0, v1, v2, u[26], m[16]);
-	MONT_MAC(w0, w1, w2, u[27], m[15]);
-	MONT_MAC(t0, t1, t2, u[28], m[14]);
-	MONT_MAC(v0, v1, v2, u[29], m[13]);
-	MONT_MAC(w0, w1, w2, u[30], m[12]);
-	MONT_MAC(t0, t1, t2, u[31], m[11]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[10] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 43 */
-	MONT_MUL(s0, s1, s2, a[12], a[31]);
-	MONT_MUL(c0, c1, c2, a[13], a[30]);
-	MONT_MAC(s0, s1, s2, a[14], a[29]);
-	MONT_MAC(c0, c1, c2, a[15], a[28]);
-	MONT_MAC(s0, s1, s2, a[16], a[27]);
-	MONT_MAC(c0, c1, c2, a[17], a[26]);
-	MONT_MAC(s0, s1, s2, a[18], a[25]);
-	MONT_MAC(c0, c1, c2, a[19], a[24]);
-	MONT_MAC(s0, s1, s2, a[20], a[23]);
-	MONT_MAC(c0, c1, c2, a[21], a[22]);
-	MONT_MAC(t0, t1, t2, u[12], m[31]);
-	MONT_MUL(v0, v1, v2, u[13], m[30]);
-	MONT_MUL(w0, w1, w2, u[14], m[29]);
-	MONT_MAC(t0, t1, t2, u[15], m[28]);
-	MONT_MAC(v0, v1, v2, u[16], m[27]);
-	MONT_MAC(w0, w1, w2, u[17], m[26]);
-	MONT_MAC(t0, t1, t2, u[18], m[25]);
-	MONT_MAC(v0, v1, v2, u[19], m[24]);
-	MONT_MAC(w0, w1, w2, u[20], m[23]);
-	MONT_MAC(t0, t1, t2, u[21], m[22]);
-	MONT_MAC(v0, v1, v2, u[22], m[21]);
-	MONT_MAC(w0, w1, w2, u[23], m[20]);
-	MONT_MAC(t0, t1, t2, u[24], m[19]);
-	MONT_MAC(v0, v1, v2, u[25], m[18]);
-	MONT_MAC(w0, w1, w2, u[26], m[17]);
-	MONT_MAC(t0, t1, t2, u[27], m[16]);
-	MONT_MAC(v0, v1, v2, u[28], m[15]);
-	MONT_MAC(w0, w1, w2, u[29], m[14]);
-	MONT_MAC(t0, t1, t2, u[30], m[13]);
-	MONT_MAC(v0, v1, v2, u[31], m[12]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[11] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 44 */
-	MONT_MUL(s0, s1, s2, a[13], a[31]);
-	MONT_MUL(c0, c1, c2, a[14], a[30]);
-	MONT_MAC(s0, s1, s2, a[15], a[29]);
-	MONT_MAC(c0, c1, c2, a[16], a[28]);
-	MONT_MAC(s0, s1, s2, a[17], a[27]);
-	MONT_MAC(c0, c1, c2, a[18], a[26]);
-	MONT_MAC(s0, s1, s2, a[19], a[25]);
-	MONT_MAC(c0, c1, c2, a[20], a[24]);
-	MONT_MAC(s0, s1, s2, a[21], a[23]);
-	MONT_MAC(t0, t1, t2, a[22], a[22]);
-	MONT_MUL(v0, v1, v2, u[13], m[31]);
-	MONT_MUL(w0, w1, w2, u[14], m[30]);
-	MONT_MAC(t0, t1, t2, u[15], m[29]);
-	MONT_MAC(v0, v1, v2, u[16], m[28]);
-	MONT_MAC(w0, w1, w2, u[17], m[27]);
-	MONT_MAC(t0, t1, t2, u[18], m[26]);
-	MONT_MAC(v0, v1, v2, u[19], m[25]);
-	MONT_MAC(w0, w1, w2, u[20], m[24]);
-	MONT_MAC(t0, t1, t2, u[21], m[23]);
-	MONT_MAC(v0, v1, v2, u[22], m[22]);
-	MONT_MAC(w0, w1, w2, u[23], m[21]);
-	MONT_MAC(t0, t1, t2, u[24], m[20]);
-	MONT_MAC(v0, v1, v2, u[25], m[19]);
-	MONT_MAC(w0, w1, w2, u[26], m[18]);
-	MONT_MAC(t0, t1, t2, u[27], m[17]);
-	MONT_MAC(v0, v1, v2, u[28], m[16]);
-	MONT_MAC(w0, w1, w2, u[29], m[15]);
-	MONT_MAC(t0, t1, t2, u[30], m[14]);
-	MONT_MAC(v0, v1, v2, u[31], m[13]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[12] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 45 */
-	MONT_MUL(s0, s1, s2, a[14], a[31]);
-	MONT_MUL(c0, c1, c2, a[15], a[30]);
-	MONT_MAC(s0, s1, s2, a[16], a[29]);
-	MONT_MAC(c0, c1, c2, a[17], a[28]);
-	MONT_MAC(s0, s1, s2, a[18], a[27]);
-	MONT_MAC(c0, c1, c2, a[19], a[26]);
-	MONT_MAC(s0, s1, s2, a[20], a[25]);
-	MONT_MAC(c0, c1, c2, a[21], a[24]);
-	MONT_MAC(s0, s1, s2, a[22], a[23]);
-	MONT_MAC(t0, t1, t2, u[14], m[31]);
-	MONT_MUL(v0, v1, v2, u[15], m[30]);
-	MONT_MUL(w0, w1, w2, u[16], m[29]);
-	MONT_MAC(t0, t1, t2, u[17], m[28]);
-	MONT_MAC(v0, v1, v2, u[18], m[27]);
-	MONT_MAC(w0, w1, w2, u[19], m[26]);
-	MONT_MAC(t0, t1, t2, u[20], m[25]);
-	MONT_MAC(v0, v1, v2, u[21], m[24]);
-	MONT_MAC(w0, w1, w2, u[22], m[23]);
-	MONT_MAC(t0, t1, t2, u[23], m[22]);
-	MONT_MAC(v0, v1, v2, u[24], m[21]);
-	MONT_MAC(w0, w1, w2, u[25], m[20]);
-	MONT_MAC(t0, t1, t2, u[26], m[19]);
-	MONT_MAC(v0, v1, v2, u[27], m[18]);
-	MONT_MAC(w0, w1, w2, u[28], m[17]);
-	MONT_MAC(t0, t1, t2, u[29], m[16]);
-	MONT_MAC(v0, v1, v2, u[30], m[15]);
-	MONT_MAC(w0, w1, w2, u[31], m[14]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[13] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 46 */
-	MONT_MUL(s0, s1, s2, a[15], a[31]);
-	MONT_MUL(c0, c1, c2, a[16], a[30]);
-	MONT_MAC(s0, s1, s2, a[17], a[29]);
-	MONT_MAC(c0, c1, c2, a[18], a[28]);
-	MONT_MAC(s0, s1, s2, a[19], a[27]);
-	MONT_MAC(c0, c1, c2, a[20], a[26]);
-	MONT_MAC(s0, s1, s2, a[21], a[25]);
-	MONT_MAC(c0, c1, c2, a[22], a[24]);
-	MONT_MAC(t0, t1, t2, a[23], a[23]);
-	MONT_MUL(v0, v1, v2, u[15], m[31]);
-	MONT_MUL(w0, w1, w2, u[16], m[30]);
-	MONT_MAC(t0, t1, t2, u[17], m[29]);
-	MONT_MAC(v0, v1, v2, u[18], m[28]);
-	MONT_MAC(w0, w1, w2, u[19], m[27]);
-	MONT_MAC(t0, t1, t2, u[20], m[26]);
-	MONT_MAC(v0, v1, v2, u[21], m[25]);
-	MONT_MAC(w0, w1, w2, u[22], m[24]);
-	MONT_MAC(t0, t1, t2, u[23], m[23]);
-	MONT_MAC(v0, v1, v2, u[24], m[22]);
-	MONT_MAC(w0, w1, w2, u[25], m[21]);
-	MONT_MAC(t0, t1, t2, u[26], m[20]);
-	MONT_MAC(v0, v1, v2, u[27], m[19]);
-	MONT_MAC(w0, w1, w2, u[28], m[18]);
-	MONT_MAC(t0, t1, t2, u[29], m[17]);
-	MONT_MAC(v0, v1, v2, u[30], m[16]);
-	MONT_MAC(w0, w1, w2, u[31], m[15]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[14] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 47 */
-	MONT_MUL(s0, s1, s2, a[16], a[31]);
-	MONT_MUL(c0, c1, c2, a[17], a[30]);
-	MONT_MAC(s0, s1, s2, a[18], a[29]);
-	MONT_MAC(c0, c1, c2, a[19], a[28]);
-	MONT_MAC(s0, s1, s2, a[20], a[27]);
-	MONT_MAC(c0, c1, c2, a[21], a[26]);
-	MONT_MAC(s0, s1, s2, a[22], a[25]);
-	MONT_MAC(c0, c1, c2, a[23], a[24]);
-	MONT_MAC(t0, t1, t2, u[16], m[31]);
-	MONT_MUL(v0, v1, v2, u[17], m[30]);
-	MONT_MUL(w0, w1, w2, u[18], m[29]);
-	MONT_MAC(t0, t1, t2, u[19], m[28]);
-	MONT_MAC(v0, v1, v2, u[20], m[27]);
-	MONT_MAC(w0, w1, w2, u[21], m[26]);
-	MONT_MAC(t0, t1, t2, u[22], m[25]);
-	MONT_MAC(v0, v1, v2, u[23], m[24]);
-	MONT_MAC(w0, w1, w2, u[24], m[23]);
-	MONT_MAC(t0, t1, t2, u[25], m[22]);
-	MONT_MAC(v0, v1, v2, u[26], m[21]);
-	MONT_MAC(w0, w1, w2, u[27], m[20]);
-	MONT_MAC(t0, t1, t2, u[28], m[19]);
-	MONT_MAC(v0, v1, v2, u[29], m[18]);
-	MONT_MAC(w0, w1, w2, u[30], m[17]);
-	MONT_MAC(t0, t1, t2, u[31], m[16]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[15] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 48 */
-	MONT_MUL(s0, s1, s2, a[17], a[31]);
-	MONT_MUL(c0, c1, c2, a[18], a[30]);
-	MONT_MAC(s0, s1, s2, a[19], a[29]);
-	MONT_MAC(c0, c1, c2, a[20], a[28]);
-	MONT_MAC(s0, s1, s2, a[21], a[27]);
-	MONT_MAC(c0, c1, c2, a[22], a[26]);
-	MONT_MAC(s0, s1, s2, a[23], a[25]);
-	MONT_MAC(t0, t1, t2, a[24], a[24]);
-	MONT_MUL(v0, v1, v2, u[17], m[31]);
-	MONT_MUL(w0, w1, w2, u[18], m[30]);
-	MONT_MAC(t0, t1, t2, u[19], m[29]);
-	MONT_MAC(v0, v1, v2, u[20], m[28]);
-	MONT_MAC(w0, w1, w2, u[21], m[27]);
-	MONT_MAC(t0, t1, t2, u[22], m[26]);
-	MONT_MAC(v0, v1, v2, u[23], m[25]);
-	MONT_MAC(w0, w1, w2, u[24], m[24]);
-	MONT_MAC(t0, t1, t2, u[25], m[23]);
-	MONT_MAC(v0, v1, v2, u[26], m[22]);
-	MONT_MAC(w0, w1, w2, u[27], m[21]);
-	MONT_MAC(t0, t1, t2, u[28], m[20]);
-	MONT_MAC(v0, v1, v2, u[29], m[19]);
-	MONT_MAC(w0, w1, w2, u[30], m[18]);
-	MONT_MAC(t0, t1, t2, u[31], m[17]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[16] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 49 */
-	MONT_MUL(s0, s1, s2, a[18], a[31]);
-	MONT_MUL(c0, c1, c2, a[19], a[30]);
-	MONT_MAC(s0, s1, s2, a[20], a[29]);
-	MONT_MAC(c0, c1, c2, a[21], a[28]);
-	MONT_MAC(s0, s1, s2, a[22], a[27]);
-	MONT_MAC(c0, c1, c2, a[23], a[26]);
-	MONT_MAC(s0, s1, s2, a[24], a[25]);
-	MONT_MAC(t0, t1, t2, u[18], m[31]);
-	MONT_MUL(v0, v1, v2, u[19], m[30]);
-	MONT_MUL(w0, w1, w2, u[20], m[29]);
-	MONT_MAC(t0, t1, t2, u[21], m[28]);
-	MONT_MAC(v0, v1, v2, u[22], m[27]);
-	MONT_MAC(w0, w1, w2, u[23], m[26]);
-	MONT_MAC(t0, t1, t2, u[24], m[25]);
-	MONT_MAC(v0, v1, v2, u[25], m[24]);
-	MONT_MAC(w0, w1, w2, u[26], m[23]);
-	MONT_MAC(t0, t1, t2, u[27], m[22]);
-	MONT_MAC(v0, v1, v2, u[28], m[21]);
-	MONT_MAC(w0, w1, w2, u[29], m[20]);
-	MONT_MAC(t0, t1, t2, u[30], m[19]);
-	MONT_MAC(v0, v1, v2, u[31], m[18]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[17] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 50 */
-	MONT_MUL(s0, s1, s2, a[19], a[31]);
-	MONT_MUL(c0, c1, c2, a[20], a[30]);
-	MONT_MAC(s0, s1, s2, a[21], a[29]);
-	MONT_MAC(c0, c1, c2, a[22], a[28]);
-	MONT_MAC(s0, s1, s2, a[23], a[27]);
-	MONT_MAC(c0, c1, c2, a[24], a[26]);
-	MONT_MAC(t0, t1, t2, a[25], a[25]);
-	MONT_MUL(v0, v1, v2, u[19], m[31]);
-	MONT_MUL(w0, w1, w2, u[20], m[30]);
-	MONT_MAC(t0, t1, t2, u[21], m[29]);
-	MONT_MAC(v0, v1, v2, u[22], m[28]);
-	MONT_MAC(w0, w1, w2, u[23], m[27]);
-	MONT_MAC(t0, t1, t2, u[24], m[26]);
-	MONT_MAC(v0, v1, v2, u[25], m[25]);
-	MONT_MAC(w0, w1, w2, u[26], m[24]);
-	MONT_MAC(t0, t1, t2, u[27], m[23]);
-	MONT_MAC(v0, v1, v2, u[28], m[22]);
-	MONT_MAC(w0, w1, w2, u[29], m[21]);
-	MONT_MAC(t0, t1, t2, u[30], m[20]);
-	MONT_MAC(v0, v1, v2, u[31], m[19]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[18] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 51 */
-	MONT_MUL(s0, s1, s2, a[20], a[31]);
-	MONT_MUL(c0, c1, c2, a[21], a[30]);
-	MONT_MAC(s0, s1, s2, a[22], a[29]);
-	MONT_MAC(c0, c1, c2, a[23], a[28]);
-	MONT_MAC(s0, s1, s2, a[24], a[27]);
-	MONT_MAC(c0, c1, c2, a[25], a[26]);
-	MONT_MAC(t0, t1, t2, u[20], m[31]);
-	MONT_MUL(v0, v1, v2, u[21], m[30]);
-	MONT_MUL(w0, w1, w2, u[22], m[29]);
-	MONT_MAC(t0, t1, t2, u[23], m[28]);
-	MONT_MAC(v0, v1, v2, u[24], m[27]);
-	MONT_MAC(w0, w1, w2, u[25], m[26]);
-	MONT_MAC(t0, t1, t2, u[26], m[25]);
-	MONT_MAC(v0, v1, v2, u[27], m[24]);
-	MONT_MAC(w0, w1, w2, u[28], m[23]);
-	MONT_MAC(t0, t1, t2, u[29], m[22]);
-	MONT_MAC(v0, v1, v2, u[30], m[21]);
-	MONT_MAC(w0, w1, w2, u[31], m[20]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[19] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 52 */
-	MONT_MUL(s0, s1, s2, a[21], a[31]);
-	MONT_MUL(c0, c1, c2, a[22], a[30]);
-	MONT_MAC(s0, s1, s2, a[23], a[29]);
-	MONT_MAC(c0, c1, c2, a[24], a[28]);
-	MONT_MAC(s0, s1, s2, a[25], a[27]);
-	MONT_MAC(t0, t1, t2, a[26], a[26]);
-	MONT_MUL(v0, v1, v2, u[21], m[31]);
-	MONT_MUL(w0, w1, w2, u[22], m[30]);
-	MONT_MAC(t0, t1, t2, u[23], m[29]);
-	MONT_MAC(v0, v1, v2, u[24], m[28]);
-	MONT_MAC(w0, w1, w2, u[25], m[27]);
-	MONT_MAC(t0, t1, t2, u[26], m[26]);
-	MONT_MAC(v0, v1, v2, u[27], m[25]);
-	MONT_MAC(w0, w1, w2, u[28], m[24]);
-	MONT_MAC(t0, t1, t2, u[29], m[23]);
-	MONT_MAC(v0, v1, v2, u[30], m[22]);
-	MONT_MAC(w0, w1, w2, u[31], m[21]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[20] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 53 */
-	MONT_MUL(s0, s1, s2, a[22], a[31]);
-	MONT_MUL(c0, c1, c2, a[23], a[30]);
-	MONT_MAC(s0, s1, s2, a[24], a[29]);
-	MONT_MAC(c0, c1, c2, a[25], a[28]);
-	MONT_MAC(s0, s1, s2, a[26], a[27]);
-	MONT_MAC(t0, t1, t2, u[22], m[31]);
-	MONT_MUL(v0, v1, v2, u[23], m[30]);
-	MONT_MUL(w0, w1, w2, u[24], m[29]);
-	MONT_MAC(t0, t1, t2, u[25], m[28]);
-	MONT_MAC(v0, v1, v2, u[26], m[27]);
-	MONT_MAC(w0, w1, w2, u[27], m[26]);
-	MONT_MAC(t0, t1, t2, u[28], m[25]);
-	MONT_MAC(v0, v1, v2, u[29], m[24]);
-	MONT_MAC(w0, w1, w2, u[30], m[23]);
-	MONT_MAC(t0, t1, t2, u[31], m[22]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[21] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 54 */
-	MONT_MUL(s0, s1, s2, a[23], a[31]);
-	MONT_MUL(c0, c1, c2, a[24], a[30]);
-	MONT_MAC(s0, s1, s2, a[25], a[29]);
-	MONT_MAC(c0, c1, c2, a[26], a[28]);
-	MONT_MAC(t0, t1, t2, a[27], a[27]);
-	MONT_MUL(v0, v1, v2, u[23], m[31]);
-	MONT_MUL(w0, w1, w2, u[24], m[30]);
-	MONT_MAC(t0, t1, t2, u[25], m[29]);
-	MONT_MAC(v0, v1, v2, u[26], m[28]);
-	MONT_MAC(w0, w1, w2, u[27], m[27]);
-	MONT_MAC(t0, t1, t2, u[28], m[26]);
-	MONT_MAC(v0, v1, v2, u[29], m[25]);
-	MONT_MAC(w0, w1, w2, u[30], m[24]);
-	MONT_MAC(t0, t1, t2, u[31], m[23]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[22] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 55 */
-	MONT_MUL(s0, s1, s2, a[24], a[31]);
-	MONT_MUL(c0, c1, c2, a[25], a[30]);
-	MONT_MAC(s0, s1, s2, a[26], a[29]);
-	MONT_MAC(c0, c1, c2, a[27], a[28]);
-	MONT_MAC(t0, t1, t2, u[24], m[31]);
-	MONT_MUL(v0, v1, v2, u[25], m[30]);
-	MONT_MUL(w0, w1, w2, u[26], m[29]);
-	MONT_MAC(t0, t1, t2, u[27], m[28]);
-	MONT_MAC(v0, v1, v2, u[28], m[27]);
-	MONT_MAC(w0, w1, w2, u[29], m[26]);
-	MONT_MAC(t0, t1, t2, u[30], m[25]);
-	MONT_MAC(v0, v1, v2, u[31], m[24]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[23] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 56 */
-	MONT_MUL(s0, s1, s2, a[25], a[31]);
-	MONT_MUL(c0, c1, c2, a[26], a[30]);
-	MONT_MAC(s0, s1, s2, a[27], a[29]);
-	MONT_MAC(t0, t1, t2, a[28], a[28]);
-	MONT_MUL(v0, v1, v2, u[25], m[31]);
-	MONT_MUL(w0, w1, w2, u[26], m[30]);
-	MONT_MAC(t0, t1, t2, u[27], m[29]);
-	MONT_MAC(v0, v1, v2, u[28], m[28]);
-	MONT_MAC(w0, w1, w2, u[29], m[27]);
-	MONT_MAC(t0, t1, t2, u[30], m[26]);
-	MONT_MAC(v0, v1, v2, u[31], m[25]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[24] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 57 */
-	MONT_MUL(s0, s1, s2, a[26], a[31]);
-	MONT_MUL(c0, c1, c2, a[27], a[30]);
-	MONT_MAC(s0, s1, s2, a[28], a[29]);
-	MONT_MAC(t0, t1, t2, u[26], m[31]);
-	MONT_MUL(v0, v1, v2, u[27], m[30]);
-	MONT_MUL(w0, w1, w2, u[28], m[29]);
-	MONT_MAC(t0, t1, t2, u[29], m[28]);
-	MONT_MAC(v0, v1, v2, u[30], m[27]);
-	MONT_MAC(w0, w1, w2, u[31], m[26]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[25] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 58 */
-	MONT_MUL(s0, s1, s2, a[27], a[31]);
-	MONT_MUL(c0, c1, c2, a[28], a[30]);
-	MONT_MAC(t0, t1, t2, a[29], a[29]);
-	MONT_MUL(v0, v1, v2, u[27], m[31]);
-	MONT_MUL(w0, w1, w2, u[28], m[30]);
-	MONT_MAC(t0, t1, t2, u[29], m[29]);
-	MONT_MAC(v0, v1, v2, u[30], m[28]);
-	MONT_MAC(w0, w1, w2, u[31], m[27]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[26] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 59 */
-	MONT_MUL(s0, s1, s2, a[28], a[31]);
-	MONT_MUL(c0, c1, c2, a[29], a[30]);
-	MONT_MAC(t0, t1, t2, u[28], m[31]);
-	MONT_MUL(v0, v1, v2, u[29], m[30]);
-	MONT_MUL(w0, w1, w2, u[30], m[29]);
-	MONT_MAC(t0, t1, t2, u[31], m[28]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_ADD(s0, s1, s2, c0, c1, c2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[27] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 60 */
-	MONT_MUL(s0, s1, s2, a[29], a[31]);
-	MONT_MAC(t0, t1, t2, a[30], a[30]);
-	MONT_MUL(v0, v1, v2, u[29], m[31]);
-	MONT_MUL(w0, w1, w2, u[30], m[30]);
-	MONT_MAC(t0, t1, t2, u[31], m[29]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_ADD(t0, t1, t2, w0, w1, w2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[28] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 61 */
-	MONT_MUL(s0, s1, s2, a[30], a[31]);
-	MONT_MAC(t0, t1, t2, u[30], m[31]);
-	MONT_MUL(v0, v1, v2, u[31], m[30]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	MONT_DBL(s0, s1, s2);
-	MONT_ADD(t0, t1, t2, s0, s1, s2);
-	z[29] = t0;
-	t0 = t1;
-	t1 = t2;
-	t2 = 0;
-	/* column 62 */
-	MONT_MAC(t0, t1, t2, a[31], a[31]);
-	MONT_MUL(v0, v1, v2, u[31], m[31]);
-	MONT_ADD(t0, t1, t2, v0, v1, v2);
-	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);
+ * the halves of RSA-2048, -3072 and -4096, and squaring at 48, RSA-3072's
+ * modulus.  Each answers what mont_mul and mont_sqr answer. */
+#ifndef CRYPTON_MONT_H
+#define CRYPTON_MONT_H
+
+#include "crypton_bignum.h"
+
+/* (t2:t1:t0) += x * y */
+#define MONT_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_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) += (s2:s1:s0) */
+#define MONT_ADD(t0, t1, t2, s0, s1, s2)                                \
+	__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")
+
+/* (s2:s1:s0) *= 2 */
+#define MONT_DBL(s0, s1, s2)                                            \
+	do {                                                                \
+		s2 = (s2 << 1) | (s1 >> 63);                                    \
+		s1 = (s1 << 1) | (s0 >> 63);                                    \
+		s0 <<= 1;                                                       \
+	} while (0)
+
+/* r = a * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
+static void crypton_mont_mul16(limb_t *r, const limb_t *a, const limb_t *b,
+                               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, v0, v1, v2, w0, w1, w2, borrow, take;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], b[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MAC(t0, t1, t2, a[0], b[1]);
+	MONT_MUL(v0, v1, v2, a[1], b[0]);
+	MONT_MUL(w0, w1, w2, u[0], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MAC(t0, t1, t2, a[0], b[2]);
+	MONT_MUL(v0, v1, v2, a[1], b[1]);
+	MONT_MUL(w0, w1, w2, a[2], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[2]);
+	MONT_MAC(v0, v1, v2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MAC(t0, t1, t2, a[0], b[3]);
+	MONT_MUL(v0, v1, v2, a[1], b[2]);
+	MONT_MUL(w0, w1, w2, a[2], b[1]);
+	MONT_MAC(t0, t1, t2, a[3], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[3]);
+	MONT_MAC(w0, w1, w2, u[1], m[2]);
+	MONT_MAC(t0, t1, t2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MAC(t0, t1, t2, a[0], b[4]);
+	MONT_MUL(v0, v1, v2, a[1], b[3]);
+	MONT_MUL(w0, w1, w2, a[2], b[2]);
+	MONT_MAC(t0, t1, t2, a[3], b[1]);
+	MONT_MAC(v0, v1, v2, a[4], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[4]);
+	MONT_MAC(t0, t1, t2, u[1], m[3]);
+	MONT_MAC(v0, v1, v2, u[2], m[2]);
+	MONT_MAC(w0, w1, w2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MAC(t0, t1, t2, a[0], b[5]);
+	MONT_MUL(v0, v1, v2, a[1], b[4]);
+	MONT_MUL(w0, w1, w2, a[2], b[3]);
+	MONT_MAC(t0, t1, t2, a[3], b[2]);
+	MONT_MAC(v0, v1, v2, a[4], b[1]);
+	MONT_MAC(w0, w1, w2, a[5], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MAC(v0, v1, v2, u[1], m[4]);
+	MONT_MAC(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MAC(t0, t1, t2, a[0], b[6]);
+	MONT_MUL(v0, v1, v2, a[1], b[5]);
+	MONT_MUL(w0, w1, w2, a[2], b[4]);
+	MONT_MAC(t0, t1, t2, a[3], b[3]);
+	MONT_MAC(v0, v1, v2, a[4], b[2]);
+	MONT_MAC(w0, w1, w2, a[5], b[1]);
+	MONT_MAC(t0, t1, t2, a[6], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[6]);
+	MONT_MAC(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MAC(t0, t1, t2, a[0], b[7]);
+	MONT_MUL(v0, v1, v2, a[1], b[6]);
+	MONT_MUL(w0, w1, w2, a[2], b[5]);
+	MONT_MAC(t0, t1, t2, a[3], b[4]);
+	MONT_MAC(v0, v1, v2, a[4], b[3]);
+	MONT_MAC(w0, w1, w2, a[5], b[2]);
+	MONT_MAC(t0, t1, t2, a[6], b[1]);
+	MONT_MAC(v0, v1, v2, a[7], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[7]);
+	MONT_MAC(t0, t1, t2, u[1], m[6]);
+	MONT_MAC(v0, v1, v2, u[2], m[5]);
+	MONT_MAC(w0, w1, w2, u[3], m[4]);
+	MONT_MAC(t0, t1, t2, u[4], m[3]);
+	MONT_MAC(v0, v1, v2, u[5], m[2]);
+	MONT_MAC(w0, w1, w2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MAC(t0, t1, t2, a[0], b[8]);
+	MONT_MUL(v0, v1, v2, a[1], b[7]);
+	MONT_MUL(w0, w1, w2, a[2], b[6]);
+	MONT_MAC(t0, t1, t2, a[3], b[5]);
+	MONT_MAC(v0, v1, v2, a[4], b[4]);
+	MONT_MAC(w0, w1, w2, a[5], b[3]);
+	MONT_MAC(t0, t1, t2, a[6], b[2]);
+	MONT_MAC(v0, v1, v2, a[7], b[1]);
+	MONT_MAC(w0, w1, w2, a[8], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[8]);
+	MONT_MAC(v0, v1, v2, u[1], m[7]);
+	MONT_MAC(w0, w1, w2, u[2], m[6]);
+	MONT_MAC(t0, t1, t2, u[3], m[5]);
+	MONT_MAC(v0, v1, v2, u[4], m[4]);
+	MONT_MAC(w0, w1, w2, u[5], m[3]);
+	MONT_MAC(t0, t1, t2, u[6], m[2]);
+	MONT_MAC(v0, v1, v2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MAC(t0, t1, t2, a[0], b[9]);
+	MONT_MUL(v0, v1, v2, a[1], b[8]);
+	MONT_MUL(w0, w1, w2, a[2], b[7]);
+	MONT_MAC(t0, t1, t2, a[3], b[6]);
+	MONT_MAC(v0, v1, v2, a[4], b[5]);
+	MONT_MAC(w0, w1, w2, a[5], b[4]);
+	MONT_MAC(t0, t1, t2, a[6], b[3]);
+	MONT_MAC(v0, v1, v2, a[7], b[2]);
+	MONT_MAC(w0, w1, w2, a[8], b[1]);
+	MONT_MAC(t0, t1, t2, a[9], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[9]);
+	MONT_MAC(w0, w1, w2, u[1], m[8]);
+	MONT_MAC(t0, t1, t2, u[2], m[7]);
+	MONT_MAC(v0, v1, v2, u[3], m[6]);
+	MONT_MAC(w0, w1, w2, u[4], m[5]);
+	MONT_MAC(t0, t1, t2, u[5], m[4]);
+	MONT_MAC(v0, v1, v2, u[6], m[3]);
+	MONT_MAC(w0, w1, w2, u[7], m[2]);
+	MONT_MAC(t0, t1, t2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MAC(t0, t1, t2, a[0], b[10]);
+	MONT_MUL(v0, v1, v2, a[1], b[9]);
+	MONT_MUL(w0, w1, w2, a[2], b[8]);
+	MONT_MAC(t0, t1, t2, a[3], b[7]);
+	MONT_MAC(v0, v1, v2, a[4], b[6]);
+	MONT_MAC(w0, w1, w2, a[5], b[5]);
+	MONT_MAC(t0, t1, t2, a[6], b[4]);
+	MONT_MAC(v0, v1, v2, a[7], b[3]);
+	MONT_MAC(w0, w1, w2, a[8], b[2]);
+	MONT_MAC(t0, t1, t2, a[9], b[1]);
+	MONT_MAC(v0, v1, v2, a[10], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[10]);
+	MONT_MAC(t0, t1, t2, u[1], m[9]);
+	MONT_MAC(v0, v1, v2, u[2], m[8]);
+	MONT_MAC(w0, w1, w2, u[3], m[7]);
+	MONT_MAC(t0, t1, t2, u[4], m[6]);
+	MONT_MAC(v0, v1, v2, u[5], m[5]);
+	MONT_MAC(w0, w1, w2, u[6], m[4]);
+	MONT_MAC(t0, t1, t2, u[7], m[3]);
+	MONT_MAC(v0, v1, v2, u[8], m[2]);
+	MONT_MAC(w0, w1, w2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MAC(t0, t1, t2, a[0], b[11]);
+	MONT_MUL(v0, v1, v2, a[1], b[10]);
+	MONT_MUL(w0, w1, w2, a[2], b[9]);
+	MONT_MAC(t0, t1, t2, a[3], b[8]);
+	MONT_MAC(v0, v1, v2, a[4], b[7]);
+	MONT_MAC(w0, w1, w2, a[5], b[6]);
+	MONT_MAC(t0, t1, t2, a[6], b[5]);
+	MONT_MAC(v0, v1, v2, a[7], b[4]);
+	MONT_MAC(w0, w1, w2, a[8], b[3]);
+	MONT_MAC(t0, t1, t2, a[9], b[2]);
+	MONT_MAC(v0, v1, v2, a[10], b[1]);
+	MONT_MAC(w0, w1, w2, a[11], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MAC(v0, v1, v2, u[1], m[10]);
+	MONT_MAC(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MAC(t0, t1, t2, a[0], b[12]);
+	MONT_MUL(v0, v1, v2, a[1], b[11]);
+	MONT_MUL(w0, w1, w2, a[2], b[10]);
+	MONT_MAC(t0, t1, t2, a[3], b[9]);
+	MONT_MAC(v0, v1, v2, a[4], b[8]);
+	MONT_MAC(w0, w1, w2, a[5], b[7]);
+	MONT_MAC(t0, t1, t2, a[6], b[6]);
+	MONT_MAC(v0, v1, v2, a[7], b[5]);
+	MONT_MAC(w0, w1, w2, a[8], b[4]);
+	MONT_MAC(t0, t1, t2, a[9], b[3]);
+	MONT_MAC(v0, v1, v2, a[10], b[2]);
+	MONT_MAC(w0, w1, w2, a[11], b[1]);
+	MONT_MAC(t0, t1, t2, a[12], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[12]);
+	MONT_MAC(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MAC(t0, t1, t2, a[0], b[13]);
+	MONT_MUL(v0, v1, v2, a[1], b[12]);
+	MONT_MUL(w0, w1, w2, a[2], b[11]);
+	MONT_MAC(t0, t1, t2, a[3], b[10]);
+	MONT_MAC(v0, v1, v2, a[4], b[9]);
+	MONT_MAC(w0, w1, w2, a[5], b[8]);
+	MONT_MAC(t0, t1, t2, a[6], b[7]);
+	MONT_MAC(v0, v1, v2, a[7], b[6]);
+	MONT_MAC(w0, w1, w2, a[8], b[5]);
+	MONT_MAC(t0, t1, t2, a[9], b[4]);
+	MONT_MAC(v0, v1, v2, a[10], b[3]);
+	MONT_MAC(w0, w1, w2, a[11], b[2]);
+	MONT_MAC(t0, t1, t2, a[12], b[1]);
+	MONT_MAC(v0, v1, v2, a[13], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[13]);
+	MONT_MAC(t0, t1, t2, u[1], m[12]);
+	MONT_MAC(v0, v1, v2, u[2], m[11]);
+	MONT_MAC(w0, w1, w2, u[3], m[10]);
+	MONT_MAC(t0, t1, t2, u[4], m[9]);
+	MONT_MAC(v0, v1, v2, u[5], m[8]);
+	MONT_MAC(w0, w1, w2, u[6], m[7]);
+	MONT_MAC(t0, t1, t2, u[7], m[6]);
+	MONT_MAC(v0, v1, v2, u[8], m[5]);
+	MONT_MAC(w0, w1, w2, u[9], m[4]);
+	MONT_MAC(t0, t1, t2, u[10], m[3]);
+	MONT_MAC(v0, v1, v2, u[11], m[2]);
+	MONT_MAC(w0, w1, w2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MAC(t0, t1, t2, a[0], b[14]);
+	MONT_MUL(v0, v1, v2, a[1], b[13]);
+	MONT_MUL(w0, w1, w2, a[2], b[12]);
+	MONT_MAC(t0, t1, t2, a[3], b[11]);
+	MONT_MAC(v0, v1, v2, a[4], b[10]);
+	MONT_MAC(w0, w1, w2, a[5], b[9]);
+	MONT_MAC(t0, t1, t2, a[6], b[8]);
+	MONT_MAC(v0, v1, v2, a[7], b[7]);
+	MONT_MAC(w0, w1, w2, a[8], b[6]);
+	MONT_MAC(t0, t1, t2, a[9], b[5]);
+	MONT_MAC(v0, v1, v2, a[10], b[4]);
+	MONT_MAC(w0, w1, w2, a[11], b[3]);
+	MONT_MAC(t0, t1, t2, a[12], b[2]);
+	MONT_MAC(v0, v1, v2, a[13], b[1]);
+	MONT_MAC(w0, w1, w2, a[14], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[14]);
+	MONT_MAC(v0, v1, v2, u[1], m[13]);
+	MONT_MAC(w0, w1, w2, u[2], m[12]);
+	MONT_MAC(t0, t1, t2, u[3], m[11]);
+	MONT_MAC(v0, v1, v2, u[4], m[10]);
+	MONT_MAC(w0, w1, w2, u[5], m[9]);
+	MONT_MAC(t0, t1, t2, u[6], m[8]);
+	MONT_MAC(v0, v1, v2, u[7], m[7]);
+	MONT_MAC(w0, w1, w2, u[8], m[6]);
+	MONT_MAC(t0, t1, t2, u[9], m[5]);
+	MONT_MAC(v0, v1, v2, u[10], m[4]);
+	MONT_MAC(w0, w1, w2, u[11], m[3]);
+	MONT_MAC(t0, t1, t2, u[12], m[2]);
+	MONT_MAC(v0, v1, v2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MAC(t0, t1, t2, a[0], b[15]);
+	MONT_MUL(v0, v1, v2, a[1], b[14]);
+	MONT_MUL(w0, w1, w2, a[2], b[13]);
+	MONT_MAC(t0, t1, t2, a[3], b[12]);
+	MONT_MAC(v0, v1, v2, a[4], b[11]);
+	MONT_MAC(w0, w1, w2, a[5], b[10]);
+	MONT_MAC(t0, t1, t2, a[6], b[9]);
+	MONT_MAC(v0, v1, v2, a[7], b[8]);
+	MONT_MAC(w0, w1, w2, a[8], b[7]);
+	MONT_MAC(t0, t1, t2, a[9], b[6]);
+	MONT_MAC(v0, v1, v2, a[10], b[5]);
+	MONT_MAC(w0, w1, w2, a[11], b[4]);
+	MONT_MAC(t0, t1, t2, a[12], b[3]);
+	MONT_MAC(v0, v1, v2, a[13], b[2]);
+	MONT_MAC(w0, w1, w2, a[14], b[1]);
+	MONT_MAC(t0, t1, t2, a[15], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[15]);
+	MONT_MAC(w0, w1, w2, u[1], m[14]);
+	MONT_MAC(t0, t1, t2, u[2], m[13]);
+	MONT_MAC(v0, v1, v2, u[3], m[12]);
+	MONT_MAC(w0, w1, w2, u[4], m[11]);
+	MONT_MAC(t0, t1, t2, u[5], m[10]);
+	MONT_MAC(v0, v1, v2, u[6], m[9]);
+	MONT_MAC(w0, w1, w2, u[7], m[8]);
+	MONT_MAC(t0, t1, t2, u[8], m[7]);
+	MONT_MAC(v0, v1, v2, u[9], m[6]);
+	MONT_MAC(w0, w1, w2, u[10], m[5]);
+	MONT_MAC(t0, t1, t2, u[11], m[4]);
+	MONT_MAC(v0, v1, v2, u[12], m[3]);
+	MONT_MAC(w0, w1, w2, u[13], m[2]);
+	MONT_MAC(t0, t1, t2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MAC(t0, t1, t2, a[1], b[15]);
+	MONT_MUL(v0, v1, v2, a[2], b[14]);
+	MONT_MUL(w0, w1, w2, a[3], b[13]);
+	MONT_MAC(t0, t1, t2, a[4], b[12]);
+	MONT_MAC(v0, v1, v2, a[5], b[11]);
+	MONT_MAC(w0, w1, w2, a[6], b[10]);
+	MONT_MAC(t0, t1, t2, a[7], b[9]);
+	MONT_MAC(v0, v1, v2, a[8], b[8]);
+	MONT_MAC(w0, w1, w2, a[9], b[7]);
+	MONT_MAC(t0, t1, t2, a[10], b[6]);
+	MONT_MAC(v0, v1, v2, a[11], b[5]);
+	MONT_MAC(w0, w1, w2, a[12], b[4]);
+	MONT_MAC(t0, t1, t2, a[13], b[3]);
+	MONT_MAC(v0, v1, v2, a[14], b[2]);
+	MONT_MAC(w0, w1, w2, a[15], b[1]);
+	MONT_MAC(t0, t1, t2, u[1], m[15]);
+	MONT_MAC(v0, v1, v2, u[2], m[14]);
+	MONT_MAC(w0, w1, w2, u[3], m[13]);
+	MONT_MAC(t0, t1, t2, u[4], m[12]);
+	MONT_MAC(v0, v1, v2, u[5], m[11]);
+	MONT_MAC(w0, w1, w2, u[6], m[10]);
+	MONT_MAC(t0, t1, t2, u[7], m[9]);
+	MONT_MAC(v0, v1, v2, u[8], m[8]);
+	MONT_MAC(w0, w1, w2, u[9], m[7]);
+	MONT_MAC(t0, t1, t2, u[10], m[6]);
+	MONT_MAC(v0, v1, v2, u[11], m[5]);
+	MONT_MAC(w0, w1, w2, u[12], m[4]);
+	MONT_MAC(t0, t1, t2, u[13], m[3]);
+	MONT_MAC(v0, v1, v2, u[14], m[2]);
+	MONT_MAC(w0, w1, w2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MAC(t0, t1, t2, a[2], b[15]);
+	MONT_MUL(v0, v1, v2, a[3], b[14]);
+	MONT_MUL(w0, w1, w2, a[4], b[13]);
+	MONT_MAC(t0, t1, t2, a[5], b[12]);
+	MONT_MAC(v0, v1, v2, a[6], b[11]);
+	MONT_MAC(w0, w1, w2, a[7], b[10]);
+	MONT_MAC(t0, t1, t2, a[8], b[9]);
+	MONT_MAC(v0, v1, v2, a[9], b[8]);
+	MONT_MAC(w0, w1, w2, a[10], b[7]);
+	MONT_MAC(t0, t1, t2, a[11], b[6]);
+	MONT_MAC(v0, v1, v2, a[12], b[5]);
+	MONT_MAC(w0, w1, w2, a[13], b[4]);
+	MONT_MAC(t0, t1, t2, a[14], b[3]);
+	MONT_MAC(v0, v1, v2, a[15], b[2]);
+	MONT_MAC(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MAC(t0, t1, t2, a[3], b[15]);
+	MONT_MUL(v0, v1, v2, a[4], b[14]);
+	MONT_MUL(w0, w1, w2, a[5], b[13]);
+	MONT_MAC(t0, t1, t2, a[6], b[12]);
+	MONT_MAC(v0, v1, v2, a[7], b[11]);
+	MONT_MAC(w0, w1, w2, a[8], b[10]);
+	MONT_MAC(t0, t1, t2, a[9], b[9]);
+	MONT_MAC(v0, v1, v2, a[10], b[8]);
+	MONT_MAC(w0, w1, w2, a[11], b[7]);
+	MONT_MAC(t0, t1, t2, a[12], b[6]);
+	MONT_MAC(v0, v1, v2, a[13], b[5]);
+	MONT_MAC(w0, w1, w2, a[14], b[4]);
+	MONT_MAC(t0, t1, t2, a[15], b[3]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MAC(t0, t1, t2, a[4], b[15]);
+	MONT_MUL(v0, v1, v2, a[5], b[14]);
+	MONT_MUL(w0, w1, w2, a[6], b[13]);
+	MONT_MAC(t0, t1, t2, a[7], b[12]);
+	MONT_MAC(v0, v1, v2, a[8], b[11]);
+	MONT_MAC(w0, w1, w2, a[9], b[10]);
+	MONT_MAC(t0, t1, t2, a[10], b[9]);
+	MONT_MAC(v0, v1, v2, a[11], b[8]);
+	MONT_MAC(w0, w1, w2, a[12], b[7]);
+	MONT_MAC(t0, t1, t2, a[13], b[6]);
+	MONT_MAC(v0, v1, v2, a[14], b[5]);
+	MONT_MAC(w0, w1, w2, a[15], b[4]);
+	MONT_MAC(t0, t1, t2, u[4], m[15]);
+	MONT_MAC(v0, v1, v2, u[5], m[14]);
+	MONT_MAC(w0, w1, w2, u[6], m[13]);
+	MONT_MAC(t0, t1, t2, u[7], m[12]);
+	MONT_MAC(v0, v1, v2, u[8], m[11]);
+	MONT_MAC(w0, w1, w2, u[9], m[10]);
+	MONT_MAC(t0, t1, t2, u[10], m[9]);
+	MONT_MAC(v0, v1, v2, u[11], m[8]);
+	MONT_MAC(w0, w1, w2, u[12], m[7]);
+	MONT_MAC(t0, t1, t2, u[13], m[6]);
+	MONT_MAC(v0, v1, v2, u[14], m[5]);
+	MONT_MAC(w0, w1, w2, u[15], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MAC(t0, t1, t2, a[5], b[15]);
+	MONT_MUL(v0, v1, v2, a[6], b[14]);
+	MONT_MUL(w0, w1, w2, a[7], b[13]);
+	MONT_MAC(t0, t1, t2, a[8], b[12]);
+	MONT_MAC(v0, v1, v2, a[9], b[11]);
+	MONT_MAC(w0, w1, w2, a[10], b[10]);
+	MONT_MAC(t0, t1, t2, a[11], b[9]);
+	MONT_MAC(v0, v1, v2, a[12], b[8]);
+	MONT_MAC(w0, w1, w2, a[13], b[7]);
+	MONT_MAC(t0, t1, t2, a[14], b[6]);
+	MONT_MAC(v0, v1, v2, a[15], b[5]);
+	MONT_MAC(w0, w1, w2, u[5], m[15]);
+	MONT_MAC(t0, t1, t2, u[6], m[14]);
+	MONT_MAC(v0, v1, v2, u[7], m[13]);
+	MONT_MAC(w0, w1, w2, u[8], m[12]);
+	MONT_MAC(t0, t1, t2, u[9], m[11]);
+	MONT_MAC(v0, v1, v2, u[10], m[10]);
+	MONT_MAC(w0, w1, w2, u[11], m[9]);
+	MONT_MAC(t0, t1, t2, u[12], m[8]);
+	MONT_MAC(v0, v1, v2, u[13], m[7]);
+	MONT_MAC(w0, w1, w2, u[14], m[6]);
+	MONT_MAC(t0, t1, t2, u[15], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MAC(t0, t1, t2, a[6], b[15]);
+	MONT_MUL(v0, v1, v2, a[7], b[14]);
+	MONT_MUL(w0, w1, w2, a[8], b[13]);
+	MONT_MAC(t0, t1, t2, a[9], b[12]);
+	MONT_MAC(v0, v1, v2, a[10], b[11]);
+	MONT_MAC(w0, w1, w2, a[11], b[10]);
+	MONT_MAC(t0, t1, t2, a[12], b[9]);
+	MONT_MAC(v0, v1, v2, a[13], b[8]);
+	MONT_MAC(w0, w1, w2, a[14], b[7]);
+	MONT_MAC(t0, t1, t2, a[15], b[6]);
+	MONT_MAC(v0, v1, v2, u[6], m[15]);
+	MONT_MAC(w0, w1, w2, u[7], m[14]);
+	MONT_MAC(t0, t1, t2, u[8], m[13]);
+	MONT_MAC(v0, v1, v2, u[9], m[12]);
+	MONT_MAC(w0, w1, w2, u[10], m[11]);
+	MONT_MAC(t0, t1, t2, u[11], m[10]);
+	MONT_MAC(v0, v1, v2, u[12], m[9]);
+	MONT_MAC(w0, w1, w2, u[13], m[8]);
+	MONT_MAC(t0, t1, t2, u[14], m[7]);
+	MONT_MAC(v0, v1, v2, u[15], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MAC(t0, t1, t2, a[7], b[15]);
+	MONT_MUL(v0, v1, v2, a[8], b[14]);
+	MONT_MUL(w0, w1, w2, a[9], b[13]);
+	MONT_MAC(t0, t1, t2, a[10], b[12]);
+	MONT_MAC(v0, v1, v2, a[11], b[11]);
+	MONT_MAC(w0, w1, w2, a[12], b[10]);
+	MONT_MAC(t0, t1, t2, a[13], b[9]);
+	MONT_MAC(v0, v1, v2, a[14], b[8]);
+	MONT_MAC(w0, w1, w2, a[15], b[7]);
+	MONT_MAC(t0, t1, t2, u[7], m[15]);
+	MONT_MAC(v0, v1, v2, u[8], m[14]);
+	MONT_MAC(w0, w1, w2, u[9], m[13]);
+	MONT_MAC(t0, t1, t2, u[10], m[12]);
+	MONT_MAC(v0, v1, v2, u[11], m[11]);
+	MONT_MAC(w0, w1, w2, u[12], m[10]);
+	MONT_MAC(t0, t1, t2, u[13], m[9]);
+	MONT_MAC(v0, v1, v2, u[14], m[8]);
+	MONT_MAC(w0, w1, w2, u[15], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MAC(t0, t1, t2, a[8], b[15]);
+	MONT_MUL(v0, v1, v2, a[9], b[14]);
+	MONT_MUL(w0, w1, w2, a[10], b[13]);
+	MONT_MAC(t0, t1, t2, a[11], b[12]);
+	MONT_MAC(v0, v1, v2, a[12], b[11]);
+	MONT_MAC(w0, w1, w2, a[13], b[10]);
+	MONT_MAC(t0, t1, t2, a[14], b[9]);
+	MONT_MAC(v0, v1, v2, a[15], b[8]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MAC(t0, t1, t2, a[9], b[15]);
+	MONT_MUL(v0, v1, v2, a[10], b[14]);
+	MONT_MUL(w0, w1, w2, a[11], b[13]);
+	MONT_MAC(t0, t1, t2, a[12], b[12]);
+	MONT_MAC(v0, v1, v2, a[13], b[11]);
+	MONT_MAC(w0, w1, w2, a[14], b[10]);
+	MONT_MAC(t0, t1, t2, a[15], b[9]);
+	MONT_MAC(v0, v1, v2, u[9], m[15]);
+	MONT_MAC(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MAC(t0, t1, t2, a[10], b[15]);
+	MONT_MUL(v0, v1, v2, a[11], b[14]);
+	MONT_MUL(w0, w1, w2, a[12], b[13]);
+	MONT_MAC(t0, t1, t2, a[13], b[12]);
+	MONT_MAC(v0, v1, v2, a[14], b[11]);
+	MONT_MAC(w0, w1, w2, a[15], b[10]);
+	MONT_MAC(t0, t1, t2, u[10], m[15]);
+	MONT_MAC(v0, v1, v2, u[11], m[14]);
+	MONT_MAC(w0, w1, w2, u[12], m[13]);
+	MONT_MAC(t0, t1, t2, u[13], m[12]);
+	MONT_MAC(v0, v1, v2, u[14], m[11]);
+	MONT_MAC(w0, w1, w2, u[15], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MAC(t0, t1, t2, a[11], b[15]);
+	MONT_MUL(v0, v1, v2, a[12], b[14]);
+	MONT_MUL(w0, w1, w2, a[13], b[13]);
+	MONT_MAC(t0, t1, t2, a[14], b[12]);
+	MONT_MAC(v0, v1, v2, a[15], b[11]);
+	MONT_MAC(w0, w1, w2, u[11], m[15]);
+	MONT_MAC(t0, t1, t2, u[12], m[14]);
+	MONT_MAC(v0, v1, v2, u[13], m[13]);
+	MONT_MAC(w0, w1, w2, u[14], m[12]);
+	MONT_MAC(t0, t1, t2, u[15], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MAC(t0, t1, t2, a[12], b[15]);
+	MONT_MUL(v0, v1, v2, a[13], b[14]);
+	MONT_MUL(w0, w1, w2, a[14], b[13]);
+	MONT_MAC(t0, t1, t2, a[15], b[12]);
+	MONT_MAC(v0, v1, v2, u[12], m[15]);
+	MONT_MAC(w0, w1, w2, u[13], m[14]);
+	MONT_MAC(t0, t1, t2, u[14], m[13]);
+	MONT_MAC(v0, v1, v2, u[15], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MAC(t0, t1, t2, a[13], b[15]);
+	MONT_MUL(v0, v1, v2, a[14], b[14]);
+	MONT_MUL(w0, w1, w2, a[15], b[13]);
+	MONT_MAC(t0, t1, t2, u[13], m[15]);
+	MONT_MAC(v0, v1, v2, u[14], m[14]);
+	MONT_MAC(w0, w1, w2, u[15], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MAC(t0, t1, t2, a[14], b[15]);
+	MONT_MUL(v0, v1, v2, a[15], b[14]);
+	MONT_MUL(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MAC(t0, t1, t2, a[15], b[15]);
+	MONT_MUL(v0, v1, v2, u[15], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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_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, v0, v1, v2, w0, w1, w2, borrow, take;
+	limb_t s0, s1, s2, c0, c1, c2;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], a[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MUL(s0, s1, s2, a[0], a[1]);
+	MONT_MAC(t0, t1, t2, u[0], m[1]);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MUL(s0, s1, s2, a[0], a[2]);
+	MONT_MAC(t0, t1, t2, a[1], a[1]);
+	MONT_MUL(v0, v1, v2, u[0], m[2]);
+	MONT_MUL(w0, w1, w2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MUL(s0, s1, s2, a[0], a[3]);
+	MONT_MUL(c0, c1, c2, a[1], a[2]);
+	MONT_MAC(t0, t1, t2, u[0], m[3]);
+	MONT_MUL(v0, v1, v2, u[1], m[2]);
+	MONT_MUL(w0, w1, w2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MUL(s0, s1, s2, a[0], a[4]);
+	MONT_MUL(c0, c1, c2, a[1], a[3]);
+	MONT_MAC(t0, t1, t2, a[2], a[2]);
+	MONT_MUL(v0, v1, v2, u[0], m[4]);
+	MONT_MUL(w0, w1, w2, u[1], m[3]);
+	MONT_MAC(t0, t1, t2, u[2], m[2]);
+	MONT_MAC(v0, v1, v2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MUL(s0, s1, s2, a[0], a[5]);
+	MONT_MUL(c0, c1, c2, a[1], a[4]);
+	MONT_MAC(s0, s1, s2, a[2], a[3]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MUL(v0, v1, v2, u[1], m[4]);
+	MONT_MUL(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MUL(s0, s1, s2, a[0], a[6]);
+	MONT_MUL(c0, c1, c2, a[1], a[5]);
+	MONT_MAC(s0, s1, s2, a[2], a[4]);
+	MONT_MAC(t0, t1, t2, a[3], a[3]);
+	MONT_MUL(v0, v1, v2, u[0], m[6]);
+	MONT_MUL(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MUL(s0, s1, s2, a[0], a[7]);
+	MONT_MUL(c0, c1, c2, a[1], a[6]);
+	MONT_MAC(s0, s1, s2, a[2], a[5]);
+	MONT_MAC(c0, c1, c2, a[3], a[4]);
+	MONT_MAC(t0, t1, t2, u[0], m[7]);
+	MONT_MUL(v0, v1, v2, u[1], m[6]);
+	MONT_MUL(w0, w1, w2, u[2], m[5]);
+	MONT_MAC(t0, t1, t2, u[3], m[4]);
+	MONT_MAC(v0, v1, v2, u[4], m[3]);
+	MONT_MAC(w0, w1, w2, u[5], m[2]);
+	MONT_MAC(t0, t1, t2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MUL(s0, s1, s2, a[0], a[8]);
+	MONT_MUL(c0, c1, c2, a[1], a[7]);
+	MONT_MAC(s0, s1, s2, a[2], a[6]);
+	MONT_MAC(c0, c1, c2, a[3], a[5]);
+	MONT_MAC(t0, t1, t2, a[4], a[4]);
+	MONT_MUL(v0, v1, v2, u[0], m[8]);
+	MONT_MUL(w0, w1, w2, u[1], m[7]);
+	MONT_MAC(t0, t1, t2, u[2], m[6]);
+	MONT_MAC(v0, v1, v2, u[3], m[5]);
+	MONT_MAC(w0, w1, w2, u[4], m[4]);
+	MONT_MAC(t0, t1, t2, u[5], m[3]);
+	MONT_MAC(v0, v1, v2, u[6], m[2]);
+	MONT_MAC(w0, w1, w2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MUL(s0, s1, s2, a[0], a[9]);
+	MONT_MUL(c0, c1, c2, a[1], a[8]);
+	MONT_MAC(s0, s1, s2, a[2], a[7]);
+	MONT_MAC(c0, c1, c2, a[3], a[6]);
+	MONT_MAC(s0, s1, s2, a[4], a[5]);
+	MONT_MAC(t0, t1, t2, u[0], m[9]);
+	MONT_MUL(v0, v1, v2, u[1], m[8]);
+	MONT_MUL(w0, w1, w2, u[2], m[7]);
+	MONT_MAC(t0, t1, t2, u[3], m[6]);
+	MONT_MAC(v0, v1, v2, u[4], m[5]);
+	MONT_MAC(w0, w1, w2, u[5], m[4]);
+	MONT_MAC(t0, t1, t2, u[6], m[3]);
+	MONT_MAC(v0, v1, v2, u[7], m[2]);
+	MONT_MAC(w0, w1, w2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MUL(s0, s1, s2, a[0], a[10]);
+	MONT_MUL(c0, c1, c2, a[1], a[9]);
+	MONT_MAC(s0, s1, s2, a[2], a[8]);
+	MONT_MAC(c0, c1, c2, a[3], a[7]);
+	MONT_MAC(s0, s1, s2, a[4], a[6]);
+	MONT_MAC(t0, t1, t2, a[5], a[5]);
+	MONT_MUL(v0, v1, v2, u[0], m[10]);
+	MONT_MUL(w0, w1, w2, u[1], m[9]);
+	MONT_MAC(t0, t1, t2, u[2], m[8]);
+	MONT_MAC(v0, v1, v2, u[3], m[7]);
+	MONT_MAC(w0, w1, w2, u[4], m[6]);
+	MONT_MAC(t0, t1, t2, u[5], m[5]);
+	MONT_MAC(v0, v1, v2, u[6], m[4]);
+	MONT_MAC(w0, w1, w2, u[7], m[3]);
+	MONT_MAC(t0, t1, t2, u[8], m[2]);
+	MONT_MAC(v0, v1, v2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MUL(s0, s1, s2, a[0], a[11]);
+	MONT_MUL(c0, c1, c2, a[1], a[10]);
+	MONT_MAC(s0, s1, s2, a[2], a[9]);
+	MONT_MAC(c0, c1, c2, a[3], a[8]);
+	MONT_MAC(s0, s1, s2, a[4], a[7]);
+	MONT_MAC(c0, c1, c2, a[5], a[6]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MUL(v0, v1, v2, u[1], m[10]);
+	MONT_MUL(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MUL(s0, s1, s2, a[0], a[12]);
+	MONT_MUL(c0, c1, c2, a[1], a[11]);
+	MONT_MAC(s0, s1, s2, a[2], a[10]);
+	MONT_MAC(c0, c1, c2, a[3], a[9]);
+	MONT_MAC(s0, s1, s2, a[4], a[8]);
+	MONT_MAC(c0, c1, c2, a[5], a[7]);
+	MONT_MAC(t0, t1, t2, a[6], a[6]);
+	MONT_MUL(v0, v1, v2, u[0], m[12]);
+	MONT_MUL(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MUL(s0, s1, s2, a[0], a[13]);
+	MONT_MUL(c0, c1, c2, a[1], a[12]);
+	MONT_MAC(s0, s1, s2, a[2], a[11]);
+	MONT_MAC(c0, c1, c2, a[3], a[10]);
+	MONT_MAC(s0, s1, s2, a[4], a[9]);
+	MONT_MAC(c0, c1, c2, a[5], a[8]);
+	MONT_MAC(s0, s1, s2, a[6], a[7]);
+	MONT_MAC(t0, t1, t2, u[0], m[13]);
+	MONT_MUL(v0, v1, v2, u[1], m[12]);
+	MONT_MUL(w0, w1, w2, u[2], m[11]);
+	MONT_MAC(t0, t1, t2, u[3], m[10]);
+	MONT_MAC(v0, v1, v2, u[4], m[9]);
+	MONT_MAC(w0, w1, w2, u[5], m[8]);
+	MONT_MAC(t0, t1, t2, u[6], m[7]);
+	MONT_MAC(v0, v1, v2, u[7], m[6]);
+	MONT_MAC(w0, w1, w2, u[8], m[5]);
+	MONT_MAC(t0, t1, t2, u[9], m[4]);
+	MONT_MAC(v0, v1, v2, u[10], m[3]);
+	MONT_MAC(w0, w1, w2, u[11], m[2]);
+	MONT_MAC(t0, t1, t2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MUL(s0, s1, s2, a[0], a[14]);
+	MONT_MUL(c0, c1, c2, a[1], a[13]);
+	MONT_MAC(s0, s1, s2, a[2], a[12]);
+	MONT_MAC(c0, c1, c2, a[3], a[11]);
+	MONT_MAC(s0, s1, s2, a[4], a[10]);
+	MONT_MAC(c0, c1, c2, a[5], a[9]);
+	MONT_MAC(s0, s1, s2, a[6], a[8]);
+	MONT_MAC(t0, t1, t2, a[7], a[7]);
+	MONT_MUL(v0, v1, v2, u[0], m[14]);
+	MONT_MUL(w0, w1, w2, u[1], m[13]);
+	MONT_MAC(t0, t1, t2, u[2], m[12]);
+	MONT_MAC(v0, v1, v2, u[3], m[11]);
+	MONT_MAC(w0, w1, w2, u[4], m[10]);
+	MONT_MAC(t0, t1, t2, u[5], m[9]);
+	MONT_MAC(v0, v1, v2, u[6], m[8]);
+	MONT_MAC(w0, w1, w2, u[7], m[7]);
+	MONT_MAC(t0, t1, t2, u[8], m[6]);
+	MONT_MAC(v0, v1, v2, u[9], m[5]);
+	MONT_MAC(w0, w1, w2, u[10], m[4]);
+	MONT_MAC(t0, t1, t2, u[11], m[3]);
+	MONT_MAC(v0, v1, v2, u[12], m[2]);
+	MONT_MAC(w0, w1, w2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MUL(s0, s1, s2, a[0], a[15]);
+	MONT_MUL(c0, c1, c2, a[1], a[14]);
+	MONT_MAC(s0, s1, s2, a[2], a[13]);
+	MONT_MAC(c0, c1, c2, a[3], a[12]);
+	MONT_MAC(s0, s1, s2, a[4], a[11]);
+	MONT_MAC(c0, c1, c2, a[5], a[10]);
+	MONT_MAC(s0, s1, s2, a[6], a[9]);
+	MONT_MAC(c0, c1, c2, a[7], a[8]);
+	MONT_MAC(t0, t1, t2, u[0], m[15]);
+	MONT_MUL(v0, v1, v2, u[1], m[14]);
+	MONT_MUL(w0, w1, w2, u[2], m[13]);
+	MONT_MAC(t0, t1, t2, u[3], m[12]);
+	MONT_MAC(v0, v1, v2, u[4], m[11]);
+	MONT_MAC(w0, w1, w2, u[5], m[10]);
+	MONT_MAC(t0, t1, t2, u[6], m[9]);
+	MONT_MAC(v0, v1, v2, u[7], m[8]);
+	MONT_MAC(w0, w1, w2, u[8], m[7]);
+	MONT_MAC(t0, t1, t2, u[9], m[6]);
+	MONT_MAC(v0, v1, v2, u[10], m[5]);
+	MONT_MAC(w0, w1, w2, u[11], m[4]);
+	MONT_MAC(t0, t1, t2, u[12], m[3]);
+	MONT_MAC(v0, v1, v2, u[13], m[2]);
+	MONT_MAC(w0, w1, w2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MUL(s0, s1, s2, a[1], a[15]);
+	MONT_MUL(c0, c1, c2, a[2], a[14]);
+	MONT_MAC(s0, s1, s2, a[3], a[13]);
+	MONT_MAC(c0, c1, c2, a[4], a[12]);
+	MONT_MAC(s0, s1, s2, a[5], a[11]);
+	MONT_MAC(c0, c1, c2, a[6], a[10]);
+	MONT_MAC(s0, s1, s2, a[7], a[9]);
+	MONT_MAC(t0, t1, t2, a[8], a[8]);
+	MONT_MUL(v0, v1, v2, u[1], m[15]);
+	MONT_MUL(w0, w1, w2, u[2], m[14]);
+	MONT_MAC(t0, t1, t2, u[3], m[13]);
+	MONT_MAC(v0, v1, v2, u[4], m[12]);
+	MONT_MAC(w0, w1, w2, u[5], m[11]);
+	MONT_MAC(t0, t1, t2, u[6], m[10]);
+	MONT_MAC(v0, v1, v2, u[7], m[9]);
+	MONT_MAC(w0, w1, w2, u[8], m[8]);
+	MONT_MAC(t0, t1, t2, u[9], m[7]);
+	MONT_MAC(v0, v1, v2, u[10], m[6]);
+	MONT_MAC(w0, w1, w2, u[11], m[5]);
+	MONT_MAC(t0, t1, t2, u[12], m[4]);
+	MONT_MAC(v0, v1, v2, u[13], m[3]);
+	MONT_MAC(w0, w1, w2, u[14], m[2]);
+	MONT_MAC(t0, t1, t2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MUL(s0, s1, s2, a[2], a[15]);
+	MONT_MUL(c0, c1, c2, a[3], a[14]);
+	MONT_MAC(s0, s1, s2, a[4], a[13]);
+	MONT_MAC(c0, c1, c2, a[5], a[12]);
+	MONT_MAC(s0, s1, s2, a[6], a[11]);
+	MONT_MAC(c0, c1, c2, a[7], a[10]);
+	MONT_MAC(s0, s1, s2, a[8], a[9]);
+	MONT_MAC(t0, t1, t2, u[2], m[15]);
+	MONT_MUL(v0, v1, v2, u[3], m[14]);
+	MONT_MUL(w0, w1, w2, u[4], m[13]);
+	MONT_MAC(t0, t1, t2, u[5], m[12]);
+	MONT_MAC(v0, v1, v2, u[6], m[11]);
+	MONT_MAC(w0, w1, w2, u[7], m[10]);
+	MONT_MAC(t0, t1, t2, u[8], m[9]);
+	MONT_MAC(v0, v1, v2, u[9], m[8]);
+	MONT_MAC(w0, w1, w2, u[10], m[7]);
+	MONT_MAC(t0, t1, t2, u[11], m[6]);
+	MONT_MAC(v0, v1, v2, u[12], m[5]);
+	MONT_MAC(w0, w1, w2, u[13], m[4]);
+	MONT_MAC(t0, t1, t2, u[14], m[3]);
+	MONT_MAC(v0, v1, v2, u[15], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MUL(s0, s1, s2, a[3], a[15]);
+	MONT_MUL(c0, c1, c2, a[4], a[14]);
+	MONT_MAC(s0, s1, s2, a[5], a[13]);
+	MONT_MAC(c0, c1, c2, a[6], a[12]);
+	MONT_MAC(s0, s1, s2, a[7], a[11]);
+	MONT_MAC(c0, c1, c2, a[8], a[10]);
+	MONT_MAC(t0, t1, t2, a[9], a[9]);
+	MONT_MUL(v0, v1, v2, u[3], m[15]);
+	MONT_MUL(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MUL(s0, s1, s2, a[4], a[15]);
+	MONT_MUL(c0, c1, c2, a[5], a[14]);
+	MONT_MAC(s0, s1, s2, a[6], a[13]);
+	MONT_MAC(c0, c1, c2, a[7], a[12]);
+	MONT_MAC(s0, s1, s2, a[8], a[11]);
+	MONT_MAC(c0, c1, c2, a[9], a[10]);
+	MONT_MAC(t0, t1, t2, u[4], m[15]);
+	MONT_MUL(v0, v1, v2, u[5], m[14]);
+	MONT_MUL(w0, w1, w2, u[6], m[13]);
+	MONT_MAC(t0, t1, t2, u[7], m[12]);
+	MONT_MAC(v0, v1, v2, u[8], m[11]);
+	MONT_MAC(w0, w1, w2, u[9], m[10]);
+	MONT_MAC(t0, t1, t2, u[10], m[9]);
+	MONT_MAC(v0, v1, v2, u[11], m[8]);
+	MONT_MAC(w0, w1, w2, u[12], m[7]);
+	MONT_MAC(t0, t1, t2, u[13], m[6]);
+	MONT_MAC(v0, v1, v2, u[14], m[5]);
+	MONT_MAC(w0, w1, w2, u[15], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MUL(s0, s1, s2, a[5], a[15]);
+	MONT_MUL(c0, c1, c2, a[6], a[14]);
+	MONT_MAC(s0, s1, s2, a[7], a[13]);
+	MONT_MAC(c0, c1, c2, a[8], a[12]);
+	MONT_MAC(s0, s1, s2, a[9], a[11]);
+	MONT_MAC(t0, t1, t2, a[10], a[10]);
+	MONT_MUL(v0, v1, v2, u[5], m[15]);
+	MONT_MUL(w0, w1, w2, u[6], m[14]);
+	MONT_MAC(t0, t1, t2, u[7], m[13]);
+	MONT_MAC(v0, v1, v2, u[8], m[12]);
+	MONT_MAC(w0, w1, w2, u[9], m[11]);
+	MONT_MAC(t0, t1, t2, u[10], m[10]);
+	MONT_MAC(v0, v1, v2, u[11], m[9]);
+	MONT_MAC(w0, w1, w2, u[12], m[8]);
+	MONT_MAC(t0, t1, t2, u[13], m[7]);
+	MONT_MAC(v0, v1, v2, u[14], m[6]);
+	MONT_MAC(w0, w1, w2, u[15], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MUL(s0, s1, s2, a[6], a[15]);
+	MONT_MUL(c0, c1, c2, a[7], a[14]);
+	MONT_MAC(s0, s1, s2, a[8], a[13]);
+	MONT_MAC(c0, c1, c2, a[9], a[12]);
+	MONT_MAC(s0, s1, s2, a[10], a[11]);
+	MONT_MAC(t0, t1, t2, u[6], m[15]);
+	MONT_MUL(v0, v1, v2, u[7], m[14]);
+	MONT_MUL(w0, w1, w2, u[8], m[13]);
+	MONT_MAC(t0, t1, t2, u[9], m[12]);
+	MONT_MAC(v0, v1, v2, u[10], m[11]);
+	MONT_MAC(w0, w1, w2, u[11], m[10]);
+	MONT_MAC(t0, t1, t2, u[12], m[9]);
+	MONT_MAC(v0, v1, v2, u[13], m[8]);
+	MONT_MAC(w0, w1, w2, u[14], m[7]);
+	MONT_MAC(t0, t1, t2, u[15], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MUL(s0, s1, s2, a[7], a[15]);
+	MONT_MUL(c0, c1, c2, a[8], a[14]);
+	MONT_MAC(s0, s1, s2, a[9], a[13]);
+	MONT_MAC(c0, c1, c2, a[10], a[12]);
+	MONT_MAC(t0, t1, t2, a[11], a[11]);
+	MONT_MUL(v0, v1, v2, u[7], m[15]);
+	MONT_MUL(w0, w1, w2, u[8], m[14]);
+	MONT_MAC(t0, t1, t2, u[9], m[13]);
+	MONT_MAC(v0, v1, v2, u[10], m[12]);
+	MONT_MAC(w0, w1, w2, u[11], m[11]);
+	MONT_MAC(t0, t1, t2, u[12], m[10]);
+	MONT_MAC(v0, v1, v2, u[13], m[9]);
+	MONT_MAC(w0, w1, w2, u[14], m[8]);
+	MONT_MAC(t0, t1, t2, u[15], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MUL(s0, s1, s2, a[8], a[15]);
+	MONT_MUL(c0, c1, c2, a[9], a[14]);
+	MONT_MAC(s0, s1, s2, a[10], a[13]);
+	MONT_MAC(c0, c1, c2, a[11], a[12]);
+	MONT_MAC(t0, t1, t2, u[8], m[15]);
+	MONT_MUL(v0, v1, v2, u[9], m[14]);
+	MONT_MUL(w0, w1, w2, u[10], m[13]);
+	MONT_MAC(t0, t1, t2, u[11], m[12]);
+	MONT_MAC(v0, v1, v2, u[12], m[11]);
+	MONT_MAC(w0, w1, w2, u[13], m[10]);
+	MONT_MAC(t0, t1, t2, u[14], m[9]);
+	MONT_MAC(v0, v1, v2, u[15], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MUL(s0, s1, s2, a[9], a[15]);
+	MONT_MUL(c0, c1, c2, a[10], a[14]);
+	MONT_MAC(s0, s1, s2, a[11], a[13]);
+	MONT_MAC(t0, t1, t2, a[12], a[12]);
+	MONT_MUL(v0, v1, v2, u[9], m[15]);
+	MONT_MUL(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MUL(s0, s1, s2, a[10], a[15]);
+	MONT_MUL(c0, c1, c2, a[11], a[14]);
+	MONT_MAC(s0, s1, s2, a[12], a[13]);
+	MONT_MAC(t0, t1, t2, u[10], m[15]);
+	MONT_MUL(v0, v1, v2, u[11], m[14]);
+	MONT_MUL(w0, w1, w2, u[12], m[13]);
+	MONT_MAC(t0, t1, t2, u[13], m[12]);
+	MONT_MAC(v0, v1, v2, u[14], m[11]);
+	MONT_MAC(w0, w1, w2, u[15], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MUL(s0, s1, s2, a[11], a[15]);
+	MONT_MUL(c0, c1, c2, a[12], a[14]);
+	MONT_MAC(t0, t1, t2, a[13], a[13]);
+	MONT_MUL(v0, v1, v2, u[11], m[15]);
+	MONT_MUL(w0, w1, w2, u[12], m[14]);
+	MONT_MAC(t0, t1, t2, u[13], m[13]);
+	MONT_MAC(v0, v1, v2, u[14], m[12]);
+	MONT_MAC(w0, w1, w2, u[15], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MUL(s0, s1, s2, a[12], a[15]);
+	MONT_MUL(c0, c1, c2, a[13], a[14]);
+	MONT_MAC(t0, t1, t2, u[12], m[15]);
+	MONT_MUL(v0, v1, v2, u[13], m[14]);
+	MONT_MUL(w0, w1, w2, u[14], m[13]);
+	MONT_MAC(t0, t1, t2, u[15], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MUL(s0, s1, s2, a[13], a[15]);
+	MONT_MAC(t0, t1, t2, a[14], a[14]);
+	MONT_MUL(v0, v1, v2, u[13], m[15]);
+	MONT_MUL(w0, w1, w2, u[14], m[14]);
+	MONT_MAC(t0, t1, t2, u[15], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MUL(s0, s1, s2, a[14], a[15]);
+	MONT_MAC(t0, t1, t2, u[14], m[15]);
+	MONT_MUL(v0, v1, v2, u[15], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MAC(t0, t1, t2, a[15], a[15]);
+	MONT_MUL(v0, v1, v2, u[15], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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 * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
+static void crypton_mont_mul24(limb_t *r, const limb_t *a, const limb_t *b,
+                               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, v0, v1, v2, w0, w1, w2, borrow, take;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], b[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MAC(t0, t1, t2, a[0], b[1]);
+	MONT_MUL(v0, v1, v2, a[1], b[0]);
+	MONT_MUL(w0, w1, w2, u[0], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MAC(t0, t1, t2, a[0], b[2]);
+	MONT_MUL(v0, v1, v2, a[1], b[1]);
+	MONT_MUL(w0, w1, w2, a[2], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[2]);
+	MONT_MAC(v0, v1, v2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MAC(t0, t1, t2, a[0], b[3]);
+	MONT_MUL(v0, v1, v2, a[1], b[2]);
+	MONT_MUL(w0, w1, w2, a[2], b[1]);
+	MONT_MAC(t0, t1, t2, a[3], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[3]);
+	MONT_MAC(w0, w1, w2, u[1], m[2]);
+	MONT_MAC(t0, t1, t2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MAC(t0, t1, t2, a[0], b[4]);
+	MONT_MUL(v0, v1, v2, a[1], b[3]);
+	MONT_MUL(w0, w1, w2, a[2], b[2]);
+	MONT_MAC(t0, t1, t2, a[3], b[1]);
+	MONT_MAC(v0, v1, v2, a[4], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[4]);
+	MONT_MAC(t0, t1, t2, u[1], m[3]);
+	MONT_MAC(v0, v1, v2, u[2], m[2]);
+	MONT_MAC(w0, w1, w2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MAC(t0, t1, t2, a[0], b[5]);
+	MONT_MUL(v0, v1, v2, a[1], b[4]);
+	MONT_MUL(w0, w1, w2, a[2], b[3]);
+	MONT_MAC(t0, t1, t2, a[3], b[2]);
+	MONT_MAC(v0, v1, v2, a[4], b[1]);
+	MONT_MAC(w0, w1, w2, a[5], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MAC(v0, v1, v2, u[1], m[4]);
+	MONT_MAC(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MAC(t0, t1, t2, a[0], b[6]);
+	MONT_MUL(v0, v1, v2, a[1], b[5]);
+	MONT_MUL(w0, w1, w2, a[2], b[4]);
+	MONT_MAC(t0, t1, t2, a[3], b[3]);
+	MONT_MAC(v0, v1, v2, a[4], b[2]);
+	MONT_MAC(w0, w1, w2, a[5], b[1]);
+	MONT_MAC(t0, t1, t2, a[6], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[6]);
+	MONT_MAC(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MAC(t0, t1, t2, a[0], b[7]);
+	MONT_MUL(v0, v1, v2, a[1], b[6]);
+	MONT_MUL(w0, w1, w2, a[2], b[5]);
+	MONT_MAC(t0, t1, t2, a[3], b[4]);
+	MONT_MAC(v0, v1, v2, a[4], b[3]);
+	MONT_MAC(w0, w1, w2, a[5], b[2]);
+	MONT_MAC(t0, t1, t2, a[6], b[1]);
+	MONT_MAC(v0, v1, v2, a[7], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[7]);
+	MONT_MAC(t0, t1, t2, u[1], m[6]);
+	MONT_MAC(v0, v1, v2, u[2], m[5]);
+	MONT_MAC(w0, w1, w2, u[3], m[4]);
+	MONT_MAC(t0, t1, t2, u[4], m[3]);
+	MONT_MAC(v0, v1, v2, u[5], m[2]);
+	MONT_MAC(w0, w1, w2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MAC(t0, t1, t2, a[0], b[8]);
+	MONT_MUL(v0, v1, v2, a[1], b[7]);
+	MONT_MUL(w0, w1, w2, a[2], b[6]);
+	MONT_MAC(t0, t1, t2, a[3], b[5]);
+	MONT_MAC(v0, v1, v2, a[4], b[4]);
+	MONT_MAC(w0, w1, w2, a[5], b[3]);
+	MONT_MAC(t0, t1, t2, a[6], b[2]);
+	MONT_MAC(v0, v1, v2, a[7], b[1]);
+	MONT_MAC(w0, w1, w2, a[8], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[8]);
+	MONT_MAC(v0, v1, v2, u[1], m[7]);
+	MONT_MAC(w0, w1, w2, u[2], m[6]);
+	MONT_MAC(t0, t1, t2, u[3], m[5]);
+	MONT_MAC(v0, v1, v2, u[4], m[4]);
+	MONT_MAC(w0, w1, w2, u[5], m[3]);
+	MONT_MAC(t0, t1, t2, u[6], m[2]);
+	MONT_MAC(v0, v1, v2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MAC(t0, t1, t2, a[0], b[9]);
+	MONT_MUL(v0, v1, v2, a[1], b[8]);
+	MONT_MUL(w0, w1, w2, a[2], b[7]);
+	MONT_MAC(t0, t1, t2, a[3], b[6]);
+	MONT_MAC(v0, v1, v2, a[4], b[5]);
+	MONT_MAC(w0, w1, w2, a[5], b[4]);
+	MONT_MAC(t0, t1, t2, a[6], b[3]);
+	MONT_MAC(v0, v1, v2, a[7], b[2]);
+	MONT_MAC(w0, w1, w2, a[8], b[1]);
+	MONT_MAC(t0, t1, t2, a[9], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[9]);
+	MONT_MAC(w0, w1, w2, u[1], m[8]);
+	MONT_MAC(t0, t1, t2, u[2], m[7]);
+	MONT_MAC(v0, v1, v2, u[3], m[6]);
+	MONT_MAC(w0, w1, w2, u[4], m[5]);
+	MONT_MAC(t0, t1, t2, u[5], m[4]);
+	MONT_MAC(v0, v1, v2, u[6], m[3]);
+	MONT_MAC(w0, w1, w2, u[7], m[2]);
+	MONT_MAC(t0, t1, t2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MAC(t0, t1, t2, a[0], b[10]);
+	MONT_MUL(v0, v1, v2, a[1], b[9]);
+	MONT_MUL(w0, w1, w2, a[2], b[8]);
+	MONT_MAC(t0, t1, t2, a[3], b[7]);
+	MONT_MAC(v0, v1, v2, a[4], b[6]);
+	MONT_MAC(w0, w1, w2, a[5], b[5]);
+	MONT_MAC(t0, t1, t2, a[6], b[4]);
+	MONT_MAC(v0, v1, v2, a[7], b[3]);
+	MONT_MAC(w0, w1, w2, a[8], b[2]);
+	MONT_MAC(t0, t1, t2, a[9], b[1]);
+	MONT_MAC(v0, v1, v2, a[10], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[10]);
+	MONT_MAC(t0, t1, t2, u[1], m[9]);
+	MONT_MAC(v0, v1, v2, u[2], m[8]);
+	MONT_MAC(w0, w1, w2, u[3], m[7]);
+	MONT_MAC(t0, t1, t2, u[4], m[6]);
+	MONT_MAC(v0, v1, v2, u[5], m[5]);
+	MONT_MAC(w0, w1, w2, u[6], m[4]);
+	MONT_MAC(t0, t1, t2, u[7], m[3]);
+	MONT_MAC(v0, v1, v2, u[8], m[2]);
+	MONT_MAC(w0, w1, w2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MAC(t0, t1, t2, a[0], b[11]);
+	MONT_MUL(v0, v1, v2, a[1], b[10]);
+	MONT_MUL(w0, w1, w2, a[2], b[9]);
+	MONT_MAC(t0, t1, t2, a[3], b[8]);
+	MONT_MAC(v0, v1, v2, a[4], b[7]);
+	MONT_MAC(w0, w1, w2, a[5], b[6]);
+	MONT_MAC(t0, t1, t2, a[6], b[5]);
+	MONT_MAC(v0, v1, v2, a[7], b[4]);
+	MONT_MAC(w0, w1, w2, a[8], b[3]);
+	MONT_MAC(t0, t1, t2, a[9], b[2]);
+	MONT_MAC(v0, v1, v2, a[10], b[1]);
+	MONT_MAC(w0, w1, w2, a[11], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MAC(v0, v1, v2, u[1], m[10]);
+	MONT_MAC(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MAC(t0, t1, t2, a[0], b[12]);
+	MONT_MUL(v0, v1, v2, a[1], b[11]);
+	MONT_MUL(w0, w1, w2, a[2], b[10]);
+	MONT_MAC(t0, t1, t2, a[3], b[9]);
+	MONT_MAC(v0, v1, v2, a[4], b[8]);
+	MONT_MAC(w0, w1, w2, a[5], b[7]);
+	MONT_MAC(t0, t1, t2, a[6], b[6]);
+	MONT_MAC(v0, v1, v2, a[7], b[5]);
+	MONT_MAC(w0, w1, w2, a[8], b[4]);
+	MONT_MAC(t0, t1, t2, a[9], b[3]);
+	MONT_MAC(v0, v1, v2, a[10], b[2]);
+	MONT_MAC(w0, w1, w2, a[11], b[1]);
+	MONT_MAC(t0, t1, t2, a[12], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[12]);
+	MONT_MAC(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MAC(t0, t1, t2, a[0], b[13]);
+	MONT_MUL(v0, v1, v2, a[1], b[12]);
+	MONT_MUL(w0, w1, w2, a[2], b[11]);
+	MONT_MAC(t0, t1, t2, a[3], b[10]);
+	MONT_MAC(v0, v1, v2, a[4], b[9]);
+	MONT_MAC(w0, w1, w2, a[5], b[8]);
+	MONT_MAC(t0, t1, t2, a[6], b[7]);
+	MONT_MAC(v0, v1, v2, a[7], b[6]);
+	MONT_MAC(w0, w1, w2, a[8], b[5]);
+	MONT_MAC(t0, t1, t2, a[9], b[4]);
+	MONT_MAC(v0, v1, v2, a[10], b[3]);
+	MONT_MAC(w0, w1, w2, a[11], b[2]);
+	MONT_MAC(t0, t1, t2, a[12], b[1]);
+	MONT_MAC(v0, v1, v2, a[13], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[13]);
+	MONT_MAC(t0, t1, t2, u[1], m[12]);
+	MONT_MAC(v0, v1, v2, u[2], m[11]);
+	MONT_MAC(w0, w1, w2, u[3], m[10]);
+	MONT_MAC(t0, t1, t2, u[4], m[9]);
+	MONT_MAC(v0, v1, v2, u[5], m[8]);
+	MONT_MAC(w0, w1, w2, u[6], m[7]);
+	MONT_MAC(t0, t1, t2, u[7], m[6]);
+	MONT_MAC(v0, v1, v2, u[8], m[5]);
+	MONT_MAC(w0, w1, w2, u[9], m[4]);
+	MONT_MAC(t0, t1, t2, u[10], m[3]);
+	MONT_MAC(v0, v1, v2, u[11], m[2]);
+	MONT_MAC(w0, w1, w2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MAC(t0, t1, t2, a[0], b[14]);
+	MONT_MUL(v0, v1, v2, a[1], b[13]);
+	MONT_MUL(w0, w1, w2, a[2], b[12]);
+	MONT_MAC(t0, t1, t2, a[3], b[11]);
+	MONT_MAC(v0, v1, v2, a[4], b[10]);
+	MONT_MAC(w0, w1, w2, a[5], b[9]);
+	MONT_MAC(t0, t1, t2, a[6], b[8]);
+	MONT_MAC(v0, v1, v2, a[7], b[7]);
+	MONT_MAC(w0, w1, w2, a[8], b[6]);
+	MONT_MAC(t0, t1, t2, a[9], b[5]);
+	MONT_MAC(v0, v1, v2, a[10], b[4]);
+	MONT_MAC(w0, w1, w2, a[11], b[3]);
+	MONT_MAC(t0, t1, t2, a[12], b[2]);
+	MONT_MAC(v0, v1, v2, a[13], b[1]);
+	MONT_MAC(w0, w1, w2, a[14], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[14]);
+	MONT_MAC(v0, v1, v2, u[1], m[13]);
+	MONT_MAC(w0, w1, w2, u[2], m[12]);
+	MONT_MAC(t0, t1, t2, u[3], m[11]);
+	MONT_MAC(v0, v1, v2, u[4], m[10]);
+	MONT_MAC(w0, w1, w2, u[5], m[9]);
+	MONT_MAC(t0, t1, t2, u[6], m[8]);
+	MONT_MAC(v0, v1, v2, u[7], m[7]);
+	MONT_MAC(w0, w1, w2, u[8], m[6]);
+	MONT_MAC(t0, t1, t2, u[9], m[5]);
+	MONT_MAC(v0, v1, v2, u[10], m[4]);
+	MONT_MAC(w0, w1, w2, u[11], m[3]);
+	MONT_MAC(t0, t1, t2, u[12], m[2]);
+	MONT_MAC(v0, v1, v2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MAC(t0, t1, t2, a[0], b[15]);
+	MONT_MUL(v0, v1, v2, a[1], b[14]);
+	MONT_MUL(w0, w1, w2, a[2], b[13]);
+	MONT_MAC(t0, t1, t2, a[3], b[12]);
+	MONT_MAC(v0, v1, v2, a[4], b[11]);
+	MONT_MAC(w0, w1, w2, a[5], b[10]);
+	MONT_MAC(t0, t1, t2, a[6], b[9]);
+	MONT_MAC(v0, v1, v2, a[7], b[8]);
+	MONT_MAC(w0, w1, w2, a[8], b[7]);
+	MONT_MAC(t0, t1, t2, a[9], b[6]);
+	MONT_MAC(v0, v1, v2, a[10], b[5]);
+	MONT_MAC(w0, w1, w2, a[11], b[4]);
+	MONT_MAC(t0, t1, t2, a[12], b[3]);
+	MONT_MAC(v0, v1, v2, a[13], b[2]);
+	MONT_MAC(w0, w1, w2, a[14], b[1]);
+	MONT_MAC(t0, t1, t2, a[15], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[15]);
+	MONT_MAC(w0, w1, w2, u[1], m[14]);
+	MONT_MAC(t0, t1, t2, u[2], m[13]);
+	MONT_MAC(v0, v1, v2, u[3], m[12]);
+	MONT_MAC(w0, w1, w2, u[4], m[11]);
+	MONT_MAC(t0, t1, t2, u[5], m[10]);
+	MONT_MAC(v0, v1, v2, u[6], m[9]);
+	MONT_MAC(w0, w1, w2, u[7], m[8]);
+	MONT_MAC(t0, t1, t2, u[8], m[7]);
+	MONT_MAC(v0, v1, v2, u[9], m[6]);
+	MONT_MAC(w0, w1, w2, u[10], m[5]);
+	MONT_MAC(t0, t1, t2, u[11], m[4]);
+	MONT_MAC(v0, v1, v2, u[12], m[3]);
+	MONT_MAC(w0, w1, w2, u[13], m[2]);
+	MONT_MAC(t0, t1, t2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MAC(t0, t1, t2, a[0], b[16]);
+	MONT_MUL(v0, v1, v2, a[1], b[15]);
+	MONT_MUL(w0, w1, w2, a[2], b[14]);
+	MONT_MAC(t0, t1, t2, a[3], b[13]);
+	MONT_MAC(v0, v1, v2, a[4], b[12]);
+	MONT_MAC(w0, w1, w2, a[5], b[11]);
+	MONT_MAC(t0, t1, t2, a[6], b[10]);
+	MONT_MAC(v0, v1, v2, a[7], b[9]);
+	MONT_MAC(w0, w1, w2, a[8], b[8]);
+	MONT_MAC(t0, t1, t2, a[9], b[7]);
+	MONT_MAC(v0, v1, v2, a[10], b[6]);
+	MONT_MAC(w0, w1, w2, a[11], b[5]);
+	MONT_MAC(t0, t1, t2, a[12], b[4]);
+	MONT_MAC(v0, v1, v2, a[13], b[3]);
+	MONT_MAC(w0, w1, w2, a[14], b[2]);
+	MONT_MAC(t0, t1, t2, a[15], b[1]);
+	MONT_MAC(v0, v1, v2, a[16], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[16]);
+	MONT_MAC(t0, t1, t2, u[1], m[15]);
+	MONT_MAC(v0, v1, v2, u[2], m[14]);
+	MONT_MAC(w0, w1, w2, u[3], m[13]);
+	MONT_MAC(t0, t1, t2, u[4], m[12]);
+	MONT_MAC(v0, v1, v2, u[5], m[11]);
+	MONT_MAC(w0, w1, w2, u[6], m[10]);
+	MONT_MAC(t0, t1, t2, u[7], m[9]);
+	MONT_MAC(v0, v1, v2, u[8], m[8]);
+	MONT_MAC(w0, w1, w2, u[9], m[7]);
+	MONT_MAC(t0, t1, t2, u[10], m[6]);
+	MONT_MAC(v0, v1, v2, u[11], m[5]);
+	MONT_MAC(w0, w1, w2, u[12], m[4]);
+	MONT_MAC(t0, t1, t2, u[13], m[3]);
+	MONT_MAC(v0, v1, v2, u[14], m[2]);
+	MONT_MAC(w0, w1, w2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[16] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[16], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MAC(t0, t1, t2, a[0], b[17]);
+	MONT_MUL(v0, v1, v2, a[1], b[16]);
+	MONT_MUL(w0, w1, w2, a[2], b[15]);
+	MONT_MAC(t0, t1, t2, a[3], b[14]);
+	MONT_MAC(v0, v1, v2, a[4], b[13]);
+	MONT_MAC(w0, w1, w2, a[5], b[12]);
+	MONT_MAC(t0, t1, t2, a[6], b[11]);
+	MONT_MAC(v0, v1, v2, a[7], b[10]);
+	MONT_MAC(w0, w1, w2, a[8], b[9]);
+	MONT_MAC(t0, t1, t2, a[9], b[8]);
+	MONT_MAC(v0, v1, v2, a[10], b[7]);
+	MONT_MAC(w0, w1, w2, a[11], b[6]);
+	MONT_MAC(t0, t1, t2, a[12], b[5]);
+	MONT_MAC(v0, v1, v2, a[13], b[4]);
+	MONT_MAC(w0, w1, w2, a[14], b[3]);
+	MONT_MAC(t0, t1, t2, a[15], b[2]);
+	MONT_MAC(v0, v1, v2, a[16], b[1]);
+	MONT_MAC(w0, w1, w2, a[17], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[17]);
+	MONT_MAC(v0, v1, v2, u[1], m[16]);
+	MONT_MAC(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_MAC(v0, v1, v2, u[16], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[17] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[17], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MAC(t0, t1, t2, a[0], b[18]);
+	MONT_MUL(v0, v1, v2, a[1], b[17]);
+	MONT_MUL(w0, w1, w2, a[2], b[16]);
+	MONT_MAC(t0, t1, t2, a[3], b[15]);
+	MONT_MAC(v0, v1, v2, a[4], b[14]);
+	MONT_MAC(w0, w1, w2, a[5], b[13]);
+	MONT_MAC(t0, t1, t2, a[6], b[12]);
+	MONT_MAC(v0, v1, v2, a[7], b[11]);
+	MONT_MAC(w0, w1, w2, a[8], b[10]);
+	MONT_MAC(t0, t1, t2, a[9], b[9]);
+	MONT_MAC(v0, v1, v2, a[10], b[8]);
+	MONT_MAC(w0, w1, w2, a[11], b[7]);
+	MONT_MAC(t0, t1, t2, a[12], b[6]);
+	MONT_MAC(v0, v1, v2, a[13], b[5]);
+	MONT_MAC(w0, w1, w2, a[14], b[4]);
+	MONT_MAC(t0, t1, t2, a[15], b[3]);
+	MONT_MAC(v0, v1, v2, a[16], b[2]);
+	MONT_MAC(w0, w1, w2, a[17], b[1]);
+	MONT_MAC(t0, t1, t2, a[18], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[18]);
+	MONT_MAC(w0, w1, w2, u[1], m[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[16]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_MAC(w0, w1, w2, u[16], m[2]);
+	MONT_MAC(t0, t1, t2, u[17], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[18] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[18], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MAC(t0, t1, t2, a[0], b[19]);
+	MONT_MUL(v0, v1, v2, a[1], b[18]);
+	MONT_MUL(w0, w1, w2, a[2], b[17]);
+	MONT_MAC(t0, t1, t2, a[3], b[16]);
+	MONT_MAC(v0, v1, v2, a[4], b[15]);
+	MONT_MAC(w0, w1, w2, a[5], b[14]);
+	MONT_MAC(t0, t1, t2, a[6], b[13]);
+	MONT_MAC(v0, v1, v2, a[7], b[12]);
+	MONT_MAC(w0, w1, w2, a[8], b[11]);
+	MONT_MAC(t0, t1, t2, a[9], b[10]);
+	MONT_MAC(v0, v1, v2, a[10], b[9]);
+	MONT_MAC(w0, w1, w2, a[11], b[8]);
+	MONT_MAC(t0, t1, t2, a[12], b[7]);
+	MONT_MAC(v0, v1, v2, a[13], b[6]);
+	MONT_MAC(w0, w1, w2, a[14], b[5]);
+	MONT_MAC(t0, t1, t2, a[15], b[4]);
+	MONT_MAC(v0, v1, v2, a[16], b[3]);
+	MONT_MAC(w0, w1, w2, a[17], b[2]);
+	MONT_MAC(t0, t1, t2, a[18], b[1]);
+	MONT_MAC(v0, v1, v2, a[19], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[19]);
+	MONT_MAC(t0, t1, t2, u[1], m[18]);
+	MONT_MAC(v0, v1, v2, u[2], m[17]);
+	MONT_MAC(w0, w1, w2, u[3], m[16]);
+	MONT_MAC(t0, t1, t2, u[4], m[15]);
+	MONT_MAC(v0, v1, v2, u[5], m[14]);
+	MONT_MAC(w0, w1, w2, u[6], m[13]);
+	MONT_MAC(t0, t1, t2, u[7], m[12]);
+	MONT_MAC(v0, v1, v2, u[8], m[11]);
+	MONT_MAC(w0, w1, w2, u[9], m[10]);
+	MONT_MAC(t0, t1, t2, u[10], m[9]);
+	MONT_MAC(v0, v1, v2, u[11], m[8]);
+	MONT_MAC(w0, w1, w2, u[12], m[7]);
+	MONT_MAC(t0, t1, t2, u[13], m[6]);
+	MONT_MAC(v0, v1, v2, u[14], m[5]);
+	MONT_MAC(w0, w1, w2, u[15], m[4]);
+	MONT_MAC(t0, t1, t2, u[16], m[3]);
+	MONT_MAC(v0, v1, v2, u[17], m[2]);
+	MONT_MAC(w0, w1, w2, u[18], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[19] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[19], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MAC(t0, t1, t2, a[0], b[20]);
+	MONT_MUL(v0, v1, v2, a[1], b[19]);
+	MONT_MUL(w0, w1, w2, a[2], b[18]);
+	MONT_MAC(t0, t1, t2, a[3], b[17]);
+	MONT_MAC(v0, v1, v2, a[4], b[16]);
+	MONT_MAC(w0, w1, w2, a[5], b[15]);
+	MONT_MAC(t0, t1, t2, a[6], b[14]);
+	MONT_MAC(v0, v1, v2, a[7], b[13]);
+	MONT_MAC(w0, w1, w2, a[8], b[12]);
+	MONT_MAC(t0, t1, t2, a[9], b[11]);
+	MONT_MAC(v0, v1, v2, a[10], b[10]);
+	MONT_MAC(w0, w1, w2, a[11], b[9]);
+	MONT_MAC(t0, t1, t2, a[12], b[8]);
+	MONT_MAC(v0, v1, v2, a[13], b[7]);
+	MONT_MAC(w0, w1, w2, a[14], b[6]);
+	MONT_MAC(t0, t1, t2, a[15], b[5]);
+	MONT_MAC(v0, v1, v2, a[16], b[4]);
+	MONT_MAC(w0, w1, w2, a[17], b[3]);
+	MONT_MAC(t0, t1, t2, a[18], b[2]);
+	MONT_MAC(v0, v1, v2, a[19], b[1]);
+	MONT_MAC(w0, w1, w2, a[20], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[20]);
+	MONT_MAC(v0, v1, v2, u[1], m[19]);
+	MONT_MAC(w0, w1, w2, u[2], m[18]);
+	MONT_MAC(t0, t1, t2, u[3], m[17]);
+	MONT_MAC(v0, v1, v2, u[4], m[16]);
+	MONT_MAC(w0, w1, w2, u[5], m[15]);
+	MONT_MAC(t0, t1, t2, u[6], m[14]);
+	MONT_MAC(v0, v1, v2, u[7], m[13]);
+	MONT_MAC(w0, w1, w2, u[8], m[12]);
+	MONT_MAC(t0, t1, t2, u[9], m[11]);
+	MONT_MAC(v0, v1, v2, u[10], m[10]);
+	MONT_MAC(w0, w1, w2, u[11], m[9]);
+	MONT_MAC(t0, t1, t2, u[12], m[8]);
+	MONT_MAC(v0, v1, v2, u[13], m[7]);
+	MONT_MAC(w0, w1, w2, u[14], m[6]);
+	MONT_MAC(t0, t1, t2, u[15], m[5]);
+	MONT_MAC(v0, v1, v2, u[16], m[4]);
+	MONT_MAC(w0, w1, w2, u[17], m[3]);
+	MONT_MAC(t0, t1, t2, u[18], m[2]);
+	MONT_MAC(v0, v1, v2, u[19], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[20] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[20], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MAC(t0, t1, t2, a[0], b[21]);
+	MONT_MUL(v0, v1, v2, a[1], b[20]);
+	MONT_MUL(w0, w1, w2, a[2], b[19]);
+	MONT_MAC(t0, t1, t2, a[3], b[18]);
+	MONT_MAC(v0, v1, v2, a[4], b[17]);
+	MONT_MAC(w0, w1, w2, a[5], b[16]);
+	MONT_MAC(t0, t1, t2, a[6], b[15]);
+	MONT_MAC(v0, v1, v2, a[7], b[14]);
+	MONT_MAC(w0, w1, w2, a[8], b[13]);
+	MONT_MAC(t0, t1, t2, a[9], b[12]);
+	MONT_MAC(v0, v1, v2, a[10], b[11]);
+	MONT_MAC(w0, w1, w2, a[11], b[10]);
+	MONT_MAC(t0, t1, t2, a[12], b[9]);
+	MONT_MAC(v0, v1, v2, a[13], b[8]);
+	MONT_MAC(w0, w1, w2, a[14], b[7]);
+	MONT_MAC(t0, t1, t2, a[15], b[6]);
+	MONT_MAC(v0, v1, v2, a[16], b[5]);
+	MONT_MAC(w0, w1, w2, a[17], b[4]);
+	MONT_MAC(t0, t1, t2, a[18], b[3]);
+	MONT_MAC(v0, v1, v2, a[19], b[2]);
+	MONT_MAC(w0, w1, w2, a[20], b[1]);
+	MONT_MAC(t0, t1, t2, a[21], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[21]);
+	MONT_MAC(w0, w1, w2, u[1], m[20]);
+	MONT_MAC(t0, t1, t2, u[2], m[19]);
+	MONT_MAC(v0, v1, v2, u[3], m[18]);
+	MONT_MAC(w0, w1, w2, u[4], m[17]);
+	MONT_MAC(t0, t1, t2, u[5], m[16]);
+	MONT_MAC(v0, v1, v2, u[6], m[15]);
+	MONT_MAC(w0, w1, w2, u[7], m[14]);
+	MONT_MAC(t0, t1, t2, u[8], m[13]);
+	MONT_MAC(v0, v1, v2, u[9], m[12]);
+	MONT_MAC(w0, w1, w2, u[10], m[11]);
+	MONT_MAC(t0, t1, t2, u[11], m[10]);
+	MONT_MAC(v0, v1, v2, u[12], m[9]);
+	MONT_MAC(w0, w1, w2, u[13], m[8]);
+	MONT_MAC(t0, t1, t2, u[14], m[7]);
+	MONT_MAC(v0, v1, v2, u[15], m[6]);
+	MONT_MAC(w0, w1, w2, u[16], m[5]);
+	MONT_MAC(t0, t1, t2, u[17], m[4]);
+	MONT_MAC(v0, v1, v2, u[18], m[3]);
+	MONT_MAC(w0, w1, w2, u[19], m[2]);
+	MONT_MAC(t0, t1, t2, u[20], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[21] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[21], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MAC(t0, t1, t2, a[0], b[22]);
+	MONT_MUL(v0, v1, v2, a[1], b[21]);
+	MONT_MUL(w0, w1, w2, a[2], b[20]);
+	MONT_MAC(t0, t1, t2, a[3], b[19]);
+	MONT_MAC(v0, v1, v2, a[4], b[18]);
+	MONT_MAC(w0, w1, w2, a[5], b[17]);
+	MONT_MAC(t0, t1, t2, a[6], b[16]);
+	MONT_MAC(v0, v1, v2, a[7], b[15]);
+	MONT_MAC(w0, w1, w2, a[8], b[14]);
+	MONT_MAC(t0, t1, t2, a[9], b[13]);
+	MONT_MAC(v0, v1, v2, a[10], b[12]);
+	MONT_MAC(w0, w1, w2, a[11], b[11]);
+	MONT_MAC(t0, t1, t2, a[12], b[10]);
+	MONT_MAC(v0, v1, v2, a[13], b[9]);
+	MONT_MAC(w0, w1, w2, a[14], b[8]);
+	MONT_MAC(t0, t1, t2, a[15], b[7]);
+	MONT_MAC(v0, v1, v2, a[16], b[6]);
+	MONT_MAC(w0, w1, w2, a[17], b[5]);
+	MONT_MAC(t0, t1, t2, a[18], b[4]);
+	MONT_MAC(v0, v1, v2, a[19], b[3]);
+	MONT_MAC(w0, w1, w2, a[20], b[2]);
+	MONT_MAC(t0, t1, t2, a[21], b[1]);
+	MONT_MAC(v0, v1, v2, a[22], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[22]);
+	MONT_MAC(t0, t1, t2, u[1], m[21]);
+	MONT_MAC(v0, v1, v2, u[2], m[20]);
+	MONT_MAC(w0, w1, w2, u[3], m[19]);
+	MONT_MAC(t0, t1, t2, u[4], m[18]);
+	MONT_MAC(v0, v1, v2, u[5], m[17]);
+	MONT_MAC(w0, w1, w2, u[6], m[16]);
+	MONT_MAC(t0, t1, t2, u[7], m[15]);
+	MONT_MAC(v0, v1, v2, u[8], m[14]);
+	MONT_MAC(w0, w1, w2, u[9], m[13]);
+	MONT_MAC(t0, t1, t2, u[10], m[12]);
+	MONT_MAC(v0, v1, v2, u[11], m[11]);
+	MONT_MAC(w0, w1, w2, u[12], m[10]);
+	MONT_MAC(t0, t1, t2, u[13], m[9]);
+	MONT_MAC(v0, v1, v2, u[14], m[8]);
+	MONT_MAC(w0, w1, w2, u[15], m[7]);
+	MONT_MAC(t0, t1, t2, u[16], m[6]);
+	MONT_MAC(v0, v1, v2, u[17], m[5]);
+	MONT_MAC(w0, w1, w2, u[18], m[4]);
+	MONT_MAC(t0, t1, t2, u[19], m[3]);
+	MONT_MAC(v0, v1, v2, u[20], m[2]);
+	MONT_MAC(w0, w1, w2, u[21], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[22] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[22], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MAC(t0, t1, t2, a[0], b[23]);
+	MONT_MUL(v0, v1, v2, a[1], b[22]);
+	MONT_MUL(w0, w1, w2, a[2], b[21]);
+	MONT_MAC(t0, t1, t2, a[3], b[20]);
+	MONT_MAC(v0, v1, v2, a[4], b[19]);
+	MONT_MAC(w0, w1, w2, a[5], b[18]);
+	MONT_MAC(t0, t1, t2, a[6], b[17]);
+	MONT_MAC(v0, v1, v2, a[7], b[16]);
+	MONT_MAC(w0, w1, w2, a[8], b[15]);
+	MONT_MAC(t0, t1, t2, a[9], b[14]);
+	MONT_MAC(v0, v1, v2, a[10], b[13]);
+	MONT_MAC(w0, w1, w2, a[11], b[12]);
+	MONT_MAC(t0, t1, t2, a[12], b[11]);
+	MONT_MAC(v0, v1, v2, a[13], b[10]);
+	MONT_MAC(w0, w1, w2, a[14], b[9]);
+	MONT_MAC(t0, t1, t2, a[15], b[8]);
+	MONT_MAC(v0, v1, v2, a[16], b[7]);
+	MONT_MAC(w0, w1, w2, a[17], b[6]);
+	MONT_MAC(t0, t1, t2, a[18], b[5]);
+	MONT_MAC(v0, v1, v2, a[19], b[4]);
+	MONT_MAC(w0, w1, w2, a[20], b[3]);
+	MONT_MAC(t0, t1, t2, a[21], b[2]);
+	MONT_MAC(v0, v1, v2, a[22], b[1]);
+	MONT_MAC(w0, w1, w2, a[23], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[23]);
+	MONT_MAC(v0, v1, v2, u[1], m[22]);
+	MONT_MAC(w0, w1, w2, u[2], m[21]);
+	MONT_MAC(t0, t1, t2, u[3], m[20]);
+	MONT_MAC(v0, v1, v2, u[4], m[19]);
+	MONT_MAC(w0, w1, w2, u[5], m[18]);
+	MONT_MAC(t0, t1, t2, u[6], m[17]);
+	MONT_MAC(v0, v1, v2, u[7], m[16]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_MAC(v0, v1, v2, u[16], m[7]);
+	MONT_MAC(w0, w1, w2, u[17], m[6]);
+	MONT_MAC(t0, t1, t2, u[18], m[5]);
+	MONT_MAC(v0, v1, v2, u[19], m[4]);
+	MONT_MAC(w0, w1, w2, u[20], m[3]);
+	MONT_MAC(t0, t1, t2, u[21], m[2]);
+	MONT_MAC(v0, v1, v2, u[22], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[23] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[23], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MAC(t0, t1, t2, a[1], b[23]);
+	MONT_MUL(v0, v1, v2, a[2], b[22]);
+	MONT_MUL(w0, w1, w2, a[3], b[21]);
+	MONT_MAC(t0, t1, t2, a[4], b[20]);
+	MONT_MAC(v0, v1, v2, a[5], b[19]);
+	MONT_MAC(w0, w1, w2, a[6], b[18]);
+	MONT_MAC(t0, t1, t2, a[7], b[17]);
+	MONT_MAC(v0, v1, v2, a[8], b[16]);
+	MONT_MAC(w0, w1, w2, a[9], b[15]);
+	MONT_MAC(t0, t1, t2, a[10], b[14]);
+	MONT_MAC(v0, v1, v2, a[11], b[13]);
+	MONT_MAC(w0, w1, w2, a[12], b[12]);
+	MONT_MAC(t0, t1, t2, a[13], b[11]);
+	MONT_MAC(v0, v1, v2, a[14], b[10]);
+	MONT_MAC(w0, w1, w2, a[15], b[9]);
+	MONT_MAC(t0, t1, t2, a[16], b[8]);
+	MONT_MAC(v0, v1, v2, a[17], b[7]);
+	MONT_MAC(w0, w1, w2, a[18], b[6]);
+	MONT_MAC(t0, t1, t2, a[19], b[5]);
+	MONT_MAC(v0, v1, v2, a[20], b[4]);
+	MONT_MAC(w0, w1, w2, a[21], b[3]);
+	MONT_MAC(t0, t1, t2, a[22], b[2]);
+	MONT_MAC(v0, v1, v2, a[23], b[1]);
+	MONT_MAC(w0, w1, w2, u[1], m[23]);
+	MONT_MAC(t0, t1, t2, u[2], m[22]);
+	MONT_MAC(v0, v1, v2, u[3], m[21]);
+	MONT_MAC(w0, w1, w2, u[4], m[20]);
+	MONT_MAC(t0, t1, t2, u[5], m[19]);
+	MONT_MAC(v0, v1, v2, u[6], m[18]);
+	MONT_MAC(w0, w1, w2, u[7], m[17]);
+	MONT_MAC(t0, t1, t2, u[8], m[16]);
+	MONT_MAC(v0, v1, v2, u[9], m[15]);
+	MONT_MAC(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_MAC(w0, w1, w2, u[16], m[8]);
+	MONT_MAC(t0, t1, t2, u[17], m[7]);
+	MONT_MAC(v0, v1, v2, u[18], m[6]);
+	MONT_MAC(w0, w1, w2, u[19], m[5]);
+	MONT_MAC(t0, t1, t2, u[20], m[4]);
+	MONT_MAC(v0, v1, v2, u[21], m[3]);
+	MONT_MAC(w0, w1, w2, u[22], m[2]);
+	MONT_MAC(t0, t1, t2, u[23], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MAC(t0, t1, t2, a[2], b[23]);
+	MONT_MUL(v0, v1, v2, a[3], b[22]);
+	MONT_MUL(w0, w1, w2, a[4], b[21]);
+	MONT_MAC(t0, t1, t2, a[5], b[20]);
+	MONT_MAC(v0, v1, v2, a[6], b[19]);
+	MONT_MAC(w0, w1, w2, a[7], b[18]);
+	MONT_MAC(t0, t1, t2, a[8], b[17]);
+	MONT_MAC(v0, v1, v2, a[9], b[16]);
+	MONT_MAC(w0, w1, w2, a[10], b[15]);
+	MONT_MAC(t0, t1, t2, a[11], b[14]);
+	MONT_MAC(v0, v1, v2, a[12], b[13]);
+	MONT_MAC(w0, w1, w2, a[13], b[12]);
+	MONT_MAC(t0, t1, t2, a[14], b[11]);
+	MONT_MAC(v0, v1, v2, a[15], b[10]);
+	MONT_MAC(w0, w1, w2, a[16], b[9]);
+	MONT_MAC(t0, t1, t2, a[17], b[8]);
+	MONT_MAC(v0, v1, v2, a[18], b[7]);
+	MONT_MAC(w0, w1, w2, a[19], b[6]);
+	MONT_MAC(t0, t1, t2, a[20], b[5]);
+	MONT_MAC(v0, v1, v2, a[21], b[4]);
+	MONT_MAC(w0, w1, w2, a[22], b[3]);
+	MONT_MAC(t0, t1, t2, a[23], b[2]);
+	MONT_MAC(v0, v1, v2, u[2], m[23]);
+	MONT_MAC(w0, w1, w2, u[3], m[22]);
+	MONT_MAC(t0, t1, t2, u[4], m[21]);
+	MONT_MAC(v0, v1, v2, u[5], m[20]);
+	MONT_MAC(w0, w1, w2, u[6], m[19]);
+	MONT_MAC(t0, t1, t2, u[7], m[18]);
+	MONT_MAC(v0, v1, v2, u[8], m[17]);
+	MONT_MAC(w0, w1, w2, u[9], m[16]);
+	MONT_MAC(t0, t1, t2, u[10], m[15]);
+	MONT_MAC(v0, v1, v2, u[11], m[14]);
+	MONT_MAC(w0, w1, w2, u[12], m[13]);
+	MONT_MAC(t0, t1, t2, u[13], m[12]);
+	MONT_MAC(v0, v1, v2, u[14], m[11]);
+	MONT_MAC(w0, w1, w2, u[15], m[10]);
+	MONT_MAC(t0, t1, t2, u[16], m[9]);
+	MONT_MAC(v0, v1, v2, u[17], m[8]);
+	MONT_MAC(w0, w1, w2, u[18], m[7]);
+	MONT_MAC(t0, t1, t2, u[19], m[6]);
+	MONT_MAC(v0, v1, v2, u[20], m[5]);
+	MONT_MAC(w0, w1, w2, u[21], m[4]);
+	MONT_MAC(t0, t1, t2, u[22], m[3]);
+	MONT_MAC(v0, v1, v2, u[23], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MAC(t0, t1, t2, a[3], b[23]);
+	MONT_MUL(v0, v1, v2, a[4], b[22]);
+	MONT_MUL(w0, w1, w2, a[5], b[21]);
+	MONT_MAC(t0, t1, t2, a[6], b[20]);
+	MONT_MAC(v0, v1, v2, a[7], b[19]);
+	MONT_MAC(w0, w1, w2, a[8], b[18]);
+	MONT_MAC(t0, t1, t2, a[9], b[17]);
+	MONT_MAC(v0, v1, v2, a[10], b[16]);
+	MONT_MAC(w0, w1, w2, a[11], b[15]);
+	MONT_MAC(t0, t1, t2, a[12], b[14]);
+	MONT_MAC(v0, v1, v2, a[13], b[13]);
+	MONT_MAC(w0, w1, w2, a[14], b[12]);
+	MONT_MAC(t0, t1, t2, a[15], b[11]);
+	MONT_MAC(v0, v1, v2, a[16], b[10]);
+	MONT_MAC(w0, w1, w2, a[17], b[9]);
+	MONT_MAC(t0, t1, t2, a[18], b[8]);
+	MONT_MAC(v0, v1, v2, a[19], b[7]);
+	MONT_MAC(w0, w1, w2, a[20], b[6]);
+	MONT_MAC(t0, t1, t2, a[21], b[5]);
+	MONT_MAC(v0, v1, v2, a[22], b[4]);
+	MONT_MAC(w0, w1, w2, a[23], b[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[23]);
+	MONT_MAC(v0, v1, v2, u[4], m[22]);
+	MONT_MAC(w0, w1, w2, u[5], m[21]);
+	MONT_MAC(t0, t1, t2, u[6], m[20]);
+	MONT_MAC(v0, v1, v2, u[7], m[19]);
+	MONT_MAC(w0, w1, w2, u[8], m[18]);
+	MONT_MAC(t0, t1, t2, u[9], m[17]);
+	MONT_MAC(v0, v1, v2, u[10], m[16]);
+	MONT_MAC(w0, w1, w2, u[11], m[15]);
+	MONT_MAC(t0, t1, t2, u[12], m[14]);
+	MONT_MAC(v0, v1, v2, u[13], m[13]);
+	MONT_MAC(w0, w1, w2, u[14], m[12]);
+	MONT_MAC(t0, t1, t2, u[15], m[11]);
+	MONT_MAC(v0, v1, v2, u[16], m[10]);
+	MONT_MAC(w0, w1, w2, u[17], m[9]);
+	MONT_MAC(t0, t1, t2, u[18], m[8]);
+	MONT_MAC(v0, v1, v2, u[19], m[7]);
+	MONT_MAC(w0, w1, w2, u[20], m[6]);
+	MONT_MAC(t0, t1, t2, u[21], m[5]);
+	MONT_MAC(v0, v1, v2, u[22], m[4]);
+	MONT_MAC(w0, w1, w2, u[23], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MAC(t0, t1, t2, a[4], b[23]);
+	MONT_MUL(v0, v1, v2, a[5], b[22]);
+	MONT_MUL(w0, w1, w2, a[6], b[21]);
+	MONT_MAC(t0, t1, t2, a[7], b[20]);
+	MONT_MAC(v0, v1, v2, a[8], b[19]);
+	MONT_MAC(w0, w1, w2, a[9], b[18]);
+	MONT_MAC(t0, t1, t2, a[10], b[17]);
+	MONT_MAC(v0, v1, v2, a[11], b[16]);
+	MONT_MAC(w0, w1, w2, a[12], b[15]);
+	MONT_MAC(t0, t1, t2, a[13], b[14]);
+	MONT_MAC(v0, v1, v2, a[14], b[13]);
+	MONT_MAC(w0, w1, w2, a[15], b[12]);
+	MONT_MAC(t0, t1, t2, a[16], b[11]);
+	MONT_MAC(v0, v1, v2, a[17], b[10]);
+	MONT_MAC(w0, w1, w2, a[18], b[9]);
+	MONT_MAC(t0, t1, t2, a[19], b[8]);
+	MONT_MAC(v0, v1, v2, a[20], b[7]);
+	MONT_MAC(w0, w1, w2, a[21], b[6]);
+	MONT_MAC(t0, t1, t2, a[22], b[5]);
+	MONT_MAC(v0, v1, v2, a[23], b[4]);
+	MONT_MAC(w0, w1, w2, u[4], m[23]);
+	MONT_MAC(t0, t1, t2, u[5], m[22]);
+	MONT_MAC(v0, v1, v2, u[6], m[21]);
+	MONT_MAC(w0, w1, w2, u[7], m[20]);
+	MONT_MAC(t0, t1, t2, u[8], m[19]);
+	MONT_MAC(v0, v1, v2, u[9], m[18]);
+	MONT_MAC(w0, w1, w2, u[10], m[17]);
+	MONT_MAC(t0, t1, t2, u[11], m[16]);
+	MONT_MAC(v0, v1, v2, u[12], m[15]);
+	MONT_MAC(w0, w1, w2, u[13], m[14]);
+	MONT_MAC(t0, t1, t2, u[14], m[13]);
+	MONT_MAC(v0, v1, v2, u[15], m[12]);
+	MONT_MAC(w0, w1, w2, u[16], m[11]);
+	MONT_MAC(t0, t1, t2, u[17], m[10]);
+	MONT_MAC(v0, v1, v2, u[18], m[9]);
+	MONT_MAC(w0, w1, w2, u[19], m[8]);
+	MONT_MAC(t0, t1, t2, u[20], m[7]);
+	MONT_MAC(v0, v1, v2, u[21], m[6]);
+	MONT_MAC(w0, w1, w2, u[22], m[5]);
+	MONT_MAC(t0, t1, t2, u[23], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MAC(t0, t1, t2, a[5], b[23]);
+	MONT_MUL(v0, v1, v2, a[6], b[22]);
+	MONT_MUL(w0, w1, w2, a[7], b[21]);
+	MONT_MAC(t0, t1, t2, a[8], b[20]);
+	MONT_MAC(v0, v1, v2, a[9], b[19]);
+	MONT_MAC(w0, w1, w2, a[10], b[18]);
+	MONT_MAC(t0, t1, t2, a[11], b[17]);
+	MONT_MAC(v0, v1, v2, a[12], b[16]);
+	MONT_MAC(w0, w1, w2, a[13], b[15]);
+	MONT_MAC(t0, t1, t2, a[14], b[14]);
+	MONT_MAC(v0, v1, v2, a[15], b[13]);
+	MONT_MAC(w0, w1, w2, a[16], b[12]);
+	MONT_MAC(t0, t1, t2, a[17], b[11]);
+	MONT_MAC(v0, v1, v2, a[18], b[10]);
+	MONT_MAC(w0, w1, w2, a[19], b[9]);
+	MONT_MAC(t0, t1, t2, a[20], b[8]);
+	MONT_MAC(v0, v1, v2, a[21], b[7]);
+	MONT_MAC(w0, w1, w2, a[22], b[6]);
+	MONT_MAC(t0, t1, t2, a[23], b[5]);
+	MONT_MAC(v0, v1, v2, u[5], m[23]);
+	MONT_MAC(w0, w1, w2, u[6], m[22]);
+	MONT_MAC(t0, t1, t2, u[7], m[21]);
+	MONT_MAC(v0, v1, v2, u[8], m[20]);
+	MONT_MAC(w0, w1, w2, u[9], m[19]);
+	MONT_MAC(t0, t1, t2, u[10], m[18]);
+	MONT_MAC(v0, v1, v2, u[11], m[17]);
+	MONT_MAC(w0, w1, w2, u[12], m[16]);
+	MONT_MAC(t0, t1, t2, u[13], m[15]);
+	MONT_MAC(v0, v1, v2, u[14], m[14]);
+	MONT_MAC(w0, w1, w2, u[15], m[13]);
+	MONT_MAC(t0, t1, t2, u[16], m[12]);
+	MONT_MAC(v0, v1, v2, u[17], m[11]);
+	MONT_MAC(w0, w1, w2, u[18], m[10]);
+	MONT_MAC(t0, t1, t2, u[19], m[9]);
+	MONT_MAC(v0, v1, v2, u[20], m[8]);
+	MONT_MAC(w0, w1, w2, u[21], m[7]);
+	MONT_MAC(t0, t1, t2, u[22], m[6]);
+	MONT_MAC(v0, v1, v2, u[23], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MAC(t0, t1, t2, a[6], b[23]);
+	MONT_MUL(v0, v1, v2, a[7], b[22]);
+	MONT_MUL(w0, w1, w2, a[8], b[21]);
+	MONT_MAC(t0, t1, t2, a[9], b[20]);
+	MONT_MAC(v0, v1, v2, a[10], b[19]);
+	MONT_MAC(w0, w1, w2, a[11], b[18]);
+	MONT_MAC(t0, t1, t2, a[12], b[17]);
+	MONT_MAC(v0, v1, v2, a[13], b[16]);
+	MONT_MAC(w0, w1, w2, a[14], b[15]);
+	MONT_MAC(t0, t1, t2, a[15], b[14]);
+	MONT_MAC(v0, v1, v2, a[16], b[13]);
+	MONT_MAC(w0, w1, w2, a[17], b[12]);
+	MONT_MAC(t0, t1, t2, a[18], b[11]);
+	MONT_MAC(v0, v1, v2, a[19], b[10]);
+	MONT_MAC(w0, w1, w2, a[20], b[9]);
+	MONT_MAC(t0, t1, t2, a[21], b[8]);
+	MONT_MAC(v0, v1, v2, a[22], b[7]);
+	MONT_MAC(w0, w1, w2, a[23], b[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[23]);
+	MONT_MAC(v0, v1, v2, u[7], m[22]);
+	MONT_MAC(w0, w1, w2, u[8], m[21]);
+	MONT_MAC(t0, t1, t2, u[9], m[20]);
+	MONT_MAC(v0, v1, v2, u[10], m[19]);
+	MONT_MAC(w0, w1, w2, u[11], m[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[17]);
+	MONT_MAC(v0, v1, v2, u[13], m[16]);
+	MONT_MAC(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_MAC(v0, v1, v2, u[16], m[13]);
+	MONT_MAC(w0, w1, w2, u[17], m[12]);
+	MONT_MAC(t0, t1, t2, u[18], m[11]);
+	MONT_MAC(v0, v1, v2, u[19], m[10]);
+	MONT_MAC(w0, w1, w2, u[20], m[9]);
+	MONT_MAC(t0, t1, t2, u[21], m[8]);
+	MONT_MAC(v0, v1, v2, u[22], m[7]);
+	MONT_MAC(w0, w1, w2, u[23], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MAC(t0, t1, t2, a[7], b[23]);
+	MONT_MUL(v0, v1, v2, a[8], b[22]);
+	MONT_MUL(w0, w1, w2, a[9], b[21]);
+	MONT_MAC(t0, t1, t2, a[10], b[20]);
+	MONT_MAC(v0, v1, v2, a[11], b[19]);
+	MONT_MAC(w0, w1, w2, a[12], b[18]);
+	MONT_MAC(t0, t1, t2, a[13], b[17]);
+	MONT_MAC(v0, v1, v2, a[14], b[16]);
+	MONT_MAC(w0, w1, w2, a[15], b[15]);
+	MONT_MAC(t0, t1, t2, a[16], b[14]);
+	MONT_MAC(v0, v1, v2, a[17], b[13]);
+	MONT_MAC(w0, w1, w2, a[18], b[12]);
+	MONT_MAC(t0, t1, t2, a[19], b[11]);
+	MONT_MAC(v0, v1, v2, a[20], b[10]);
+	MONT_MAC(w0, w1, w2, a[21], b[9]);
+	MONT_MAC(t0, t1, t2, a[22], b[8]);
+	MONT_MAC(v0, v1, v2, a[23], b[7]);
+	MONT_MAC(w0, w1, w2, u[7], m[23]);
+	MONT_MAC(t0, t1, t2, u[8], m[22]);
+	MONT_MAC(v0, v1, v2, u[9], m[21]);
+	MONT_MAC(w0, w1, w2, u[10], m[20]);
+	MONT_MAC(t0, t1, t2, u[11], m[19]);
+	MONT_MAC(v0, v1, v2, u[12], m[18]);
+	MONT_MAC(w0, w1, w2, u[13], m[17]);
+	MONT_MAC(t0, t1, t2, u[14], m[16]);
+	MONT_MAC(v0, v1, v2, u[15], m[15]);
+	MONT_MAC(w0, w1, w2, u[16], m[14]);
+	MONT_MAC(t0, t1, t2, u[17], m[13]);
+	MONT_MAC(v0, v1, v2, u[18], m[12]);
+	MONT_MAC(w0, w1, w2, u[19], m[11]);
+	MONT_MAC(t0, t1, t2, u[20], m[10]);
+	MONT_MAC(v0, v1, v2, u[21], m[9]);
+	MONT_MAC(w0, w1, w2, u[22], m[8]);
+	MONT_MAC(t0, t1, t2, u[23], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 31 */
+	MONT_MAC(t0, t1, t2, a[8], b[23]);
+	MONT_MUL(v0, v1, v2, a[9], b[22]);
+	MONT_MUL(w0, w1, w2, a[10], b[21]);
+	MONT_MAC(t0, t1, t2, a[11], b[20]);
+	MONT_MAC(v0, v1, v2, a[12], b[19]);
+	MONT_MAC(w0, w1, w2, a[13], b[18]);
+	MONT_MAC(t0, t1, t2, a[14], b[17]);
+	MONT_MAC(v0, v1, v2, a[15], b[16]);
+	MONT_MAC(w0, w1, w2, a[16], b[15]);
+	MONT_MAC(t0, t1, t2, a[17], b[14]);
+	MONT_MAC(v0, v1, v2, a[18], b[13]);
+	MONT_MAC(w0, w1, w2, a[19], b[12]);
+	MONT_MAC(t0, t1, t2, a[20], b[11]);
+	MONT_MAC(v0, v1, v2, a[21], b[10]);
+	MONT_MAC(w0, w1, w2, a[22], b[9]);
+	MONT_MAC(t0, t1, t2, a[23], b[8]);
+	MONT_MAC(v0, v1, v2, u[8], m[23]);
+	MONT_MAC(w0, w1, w2, u[9], m[22]);
+	MONT_MAC(t0, t1, t2, u[10], m[21]);
+	MONT_MAC(v0, v1, v2, u[11], m[20]);
+	MONT_MAC(w0, w1, w2, u[12], m[19]);
+	MONT_MAC(t0, t1, t2, u[13], m[18]);
+	MONT_MAC(v0, v1, v2, u[14], m[17]);
+	MONT_MAC(w0, w1, w2, u[15], m[16]);
+	MONT_MAC(t0, t1, t2, u[16], m[15]);
+	MONT_MAC(v0, v1, v2, u[17], m[14]);
+	MONT_MAC(w0, w1, w2, u[18], m[13]);
+	MONT_MAC(t0, t1, t2, u[19], m[12]);
+	MONT_MAC(v0, v1, v2, u[20], m[11]);
+	MONT_MAC(w0, w1, w2, u[21], m[10]);
+	MONT_MAC(t0, t1, t2, u[22], m[9]);
+	MONT_MAC(v0, v1, v2, u[23], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 32 */
+	MONT_MAC(t0, t1, t2, a[9], b[23]);
+	MONT_MUL(v0, v1, v2, a[10], b[22]);
+	MONT_MUL(w0, w1, w2, a[11], b[21]);
+	MONT_MAC(t0, t1, t2, a[12], b[20]);
+	MONT_MAC(v0, v1, v2, a[13], b[19]);
+	MONT_MAC(w0, w1, w2, a[14], b[18]);
+	MONT_MAC(t0, t1, t2, a[15], b[17]);
+	MONT_MAC(v0, v1, v2, a[16], b[16]);
+	MONT_MAC(w0, w1, w2, a[17], b[15]);
+	MONT_MAC(t0, t1, t2, a[18], b[14]);
+	MONT_MAC(v0, v1, v2, a[19], b[13]);
+	MONT_MAC(w0, w1, w2, a[20], b[12]);
+	MONT_MAC(t0, t1, t2, a[21], b[11]);
+	MONT_MAC(v0, v1, v2, a[22], b[10]);
+	MONT_MAC(w0, w1, w2, a[23], b[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[23]);
+	MONT_MAC(v0, v1, v2, u[10], m[22]);
+	MONT_MAC(w0, w1, w2, u[11], m[21]);
+	MONT_MAC(t0, t1, t2, u[12], m[20]);
+	MONT_MAC(v0, v1, v2, u[13], m[19]);
+	MONT_MAC(w0, w1, w2, u[14], m[18]);
+	MONT_MAC(t0, t1, t2, u[15], m[17]);
+	MONT_MAC(v0, v1, v2, u[16], m[16]);
+	MONT_MAC(w0, w1, w2, u[17], m[15]);
+	MONT_MAC(t0, t1, t2, u[18], m[14]);
+	MONT_MAC(v0, v1, v2, u[19], m[13]);
+	MONT_MAC(w0, w1, w2, u[20], m[12]);
+	MONT_MAC(t0, t1, t2, u[21], m[11]);
+	MONT_MAC(v0, v1, v2, u[22], m[10]);
+	MONT_MAC(w0, w1, w2, u[23], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 33 */
+	MONT_MAC(t0, t1, t2, a[10], b[23]);
+	MONT_MUL(v0, v1, v2, a[11], b[22]);
+	MONT_MUL(w0, w1, w2, a[12], b[21]);
+	MONT_MAC(t0, t1, t2, a[13], b[20]);
+	MONT_MAC(v0, v1, v2, a[14], b[19]);
+	MONT_MAC(w0, w1, w2, a[15], b[18]);
+	MONT_MAC(t0, t1, t2, a[16], b[17]);
+	MONT_MAC(v0, v1, v2, a[17], b[16]);
+	MONT_MAC(w0, w1, w2, a[18], b[15]);
+	MONT_MAC(t0, t1, t2, a[19], b[14]);
+	MONT_MAC(v0, v1, v2, a[20], b[13]);
+	MONT_MAC(w0, w1, w2, a[21], b[12]);
+	MONT_MAC(t0, t1, t2, a[22], b[11]);
+	MONT_MAC(v0, v1, v2, a[23], b[10]);
+	MONT_MAC(w0, w1, w2, u[10], m[23]);
+	MONT_MAC(t0, t1, t2, u[11], m[22]);
+	MONT_MAC(v0, v1, v2, u[12], m[21]);
+	MONT_MAC(w0, w1, w2, u[13], m[20]);
+	MONT_MAC(t0, t1, t2, u[14], m[19]);
+	MONT_MAC(v0, v1, v2, u[15], m[18]);
+	MONT_MAC(w0, w1, w2, u[16], m[17]);
+	MONT_MAC(t0, t1, t2, u[17], m[16]);
+	MONT_MAC(v0, v1, v2, u[18], m[15]);
+	MONT_MAC(w0, w1, w2, u[19], m[14]);
+	MONT_MAC(t0, t1, t2, u[20], m[13]);
+	MONT_MAC(v0, v1, v2, u[21], m[12]);
+	MONT_MAC(w0, w1, w2, u[22], m[11]);
+	MONT_MAC(t0, t1, t2, u[23], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 34 */
+	MONT_MAC(t0, t1, t2, a[11], b[23]);
+	MONT_MUL(v0, v1, v2, a[12], b[22]);
+	MONT_MUL(w0, w1, w2, a[13], b[21]);
+	MONT_MAC(t0, t1, t2, a[14], b[20]);
+	MONT_MAC(v0, v1, v2, a[15], b[19]);
+	MONT_MAC(w0, w1, w2, a[16], b[18]);
+	MONT_MAC(t0, t1, t2, a[17], b[17]);
+	MONT_MAC(v0, v1, v2, a[18], b[16]);
+	MONT_MAC(w0, w1, w2, a[19], b[15]);
+	MONT_MAC(t0, t1, t2, a[20], b[14]);
+	MONT_MAC(v0, v1, v2, a[21], b[13]);
+	MONT_MAC(w0, w1, w2, a[22], b[12]);
+	MONT_MAC(t0, t1, t2, a[23], b[11]);
+	MONT_MAC(v0, v1, v2, u[11], m[23]);
+	MONT_MAC(w0, w1, w2, u[12], m[22]);
+	MONT_MAC(t0, t1, t2, u[13], m[21]);
+	MONT_MAC(v0, v1, v2, u[14], m[20]);
+	MONT_MAC(w0, w1, w2, u[15], m[19]);
+	MONT_MAC(t0, t1, t2, u[16], m[18]);
+	MONT_MAC(v0, v1, v2, u[17], m[17]);
+	MONT_MAC(w0, w1, w2, u[18], m[16]);
+	MONT_MAC(t0, t1, t2, u[19], m[15]);
+	MONT_MAC(v0, v1, v2, u[20], m[14]);
+	MONT_MAC(w0, w1, w2, u[21], m[13]);
+	MONT_MAC(t0, t1, t2, u[22], m[12]);
+	MONT_MAC(v0, v1, v2, u[23], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 35 */
+	MONT_MAC(t0, t1, t2, a[12], b[23]);
+	MONT_MUL(v0, v1, v2, a[13], b[22]);
+	MONT_MUL(w0, w1, w2, a[14], b[21]);
+	MONT_MAC(t0, t1, t2, a[15], b[20]);
+	MONT_MAC(v0, v1, v2, a[16], b[19]);
+	MONT_MAC(w0, w1, w2, a[17], b[18]);
+	MONT_MAC(t0, t1, t2, a[18], b[17]);
+	MONT_MAC(v0, v1, v2, a[19], b[16]);
+	MONT_MAC(w0, w1, w2, a[20], b[15]);
+	MONT_MAC(t0, t1, t2, a[21], b[14]);
+	MONT_MAC(v0, v1, v2, a[22], b[13]);
+	MONT_MAC(w0, w1, w2, a[23], b[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[23]);
+	MONT_MAC(v0, v1, v2, u[13], m[22]);
+	MONT_MAC(w0, w1, w2, u[14], m[21]);
+	MONT_MAC(t0, t1, t2, u[15], m[20]);
+	MONT_MAC(v0, v1, v2, u[16], m[19]);
+	MONT_MAC(w0, w1, w2, u[17], m[18]);
+	MONT_MAC(t0, t1, t2, u[18], m[17]);
+	MONT_MAC(v0, v1, v2, u[19], m[16]);
+	MONT_MAC(w0, w1, w2, u[20], m[15]);
+	MONT_MAC(t0, t1, t2, u[21], m[14]);
+	MONT_MAC(v0, v1, v2, u[22], m[13]);
+	MONT_MAC(w0, w1, w2, u[23], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 36 */
+	MONT_MAC(t0, t1, t2, a[13], b[23]);
+	MONT_MUL(v0, v1, v2, a[14], b[22]);
+	MONT_MUL(w0, w1, w2, a[15], b[21]);
+	MONT_MAC(t0, t1, t2, a[16], b[20]);
+	MONT_MAC(v0, v1, v2, a[17], b[19]);
+	MONT_MAC(w0, w1, w2, a[18], b[18]);
+	MONT_MAC(t0, t1, t2, a[19], b[17]);
+	MONT_MAC(v0, v1, v2, a[20], b[16]);
+	MONT_MAC(w0, w1, w2, a[21], b[15]);
+	MONT_MAC(t0, t1, t2, a[22], b[14]);
+	MONT_MAC(v0, v1, v2, a[23], b[13]);
+	MONT_MAC(w0, w1, w2, u[13], m[23]);
+	MONT_MAC(t0, t1, t2, u[14], m[22]);
+	MONT_MAC(v0, v1, v2, u[15], m[21]);
+	MONT_MAC(w0, w1, w2, u[16], m[20]);
+	MONT_MAC(t0, t1, t2, u[17], m[19]);
+	MONT_MAC(v0, v1, v2, u[18], m[18]);
+	MONT_MAC(w0, w1, w2, u[19], m[17]);
+	MONT_MAC(t0, t1, t2, u[20], m[16]);
+	MONT_MAC(v0, v1, v2, u[21], m[15]);
+	MONT_MAC(w0, w1, w2, u[22], m[14]);
+	MONT_MAC(t0, t1, t2, u[23], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 37 */
+	MONT_MAC(t0, t1, t2, a[14], b[23]);
+	MONT_MUL(v0, v1, v2, a[15], b[22]);
+	MONT_MUL(w0, w1, w2, a[16], b[21]);
+	MONT_MAC(t0, t1, t2, a[17], b[20]);
+	MONT_MAC(v0, v1, v2, a[18], b[19]);
+	MONT_MAC(w0, w1, w2, a[19], b[18]);
+	MONT_MAC(t0, t1, t2, a[20], b[17]);
+	MONT_MAC(v0, v1, v2, a[21], b[16]);
+	MONT_MAC(w0, w1, w2, a[22], b[15]);
+	MONT_MAC(t0, t1, t2, a[23], b[14]);
+	MONT_MAC(v0, v1, v2, u[14], m[23]);
+	MONT_MAC(w0, w1, w2, u[15], m[22]);
+	MONT_MAC(t0, t1, t2, u[16], m[21]);
+	MONT_MAC(v0, v1, v2, u[17], m[20]);
+	MONT_MAC(w0, w1, w2, u[18], m[19]);
+	MONT_MAC(t0, t1, t2, u[19], m[18]);
+	MONT_MAC(v0, v1, v2, u[20], m[17]);
+	MONT_MAC(w0, w1, w2, u[21], m[16]);
+	MONT_MAC(t0, t1, t2, u[22], m[15]);
+	MONT_MAC(v0, v1, v2, u[23], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 38 */
+	MONT_MAC(t0, t1, t2, a[15], b[23]);
+	MONT_MUL(v0, v1, v2, a[16], b[22]);
+	MONT_MUL(w0, w1, w2, a[17], b[21]);
+	MONT_MAC(t0, t1, t2, a[18], b[20]);
+	MONT_MAC(v0, v1, v2, a[19], b[19]);
+	MONT_MAC(w0, w1, w2, a[20], b[18]);
+	MONT_MAC(t0, t1, t2, a[21], b[17]);
+	MONT_MAC(v0, v1, v2, a[22], b[16]);
+	MONT_MAC(w0, w1, w2, a[23], b[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[23]);
+	MONT_MAC(v0, v1, v2, u[16], m[22]);
+	MONT_MAC(w0, w1, w2, u[17], m[21]);
+	MONT_MAC(t0, t1, t2, u[18], m[20]);
+	MONT_MAC(v0, v1, v2, u[19], m[19]);
+	MONT_MAC(w0, w1, w2, u[20], m[18]);
+	MONT_MAC(t0, t1, t2, u[21], m[17]);
+	MONT_MAC(v0, v1, v2, u[22], m[16]);
+	MONT_MAC(w0, w1, w2, u[23], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[14] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 39 */
+	MONT_MAC(t0, t1, t2, a[16], b[23]);
+	MONT_MUL(v0, v1, v2, a[17], b[22]);
+	MONT_MUL(w0, w1, w2, a[18], b[21]);
+	MONT_MAC(t0, t1, t2, a[19], b[20]);
+	MONT_MAC(v0, v1, v2, a[20], b[19]);
+	MONT_MAC(w0, w1, w2, a[21], b[18]);
+	MONT_MAC(t0, t1, t2, a[22], b[17]);
+	MONT_MAC(v0, v1, v2, a[23], b[16]);
+	MONT_MAC(w0, w1, w2, u[16], m[23]);
+	MONT_MAC(t0, t1, t2, u[17], m[22]);
+	MONT_MAC(v0, v1, v2, u[18], m[21]);
+	MONT_MAC(w0, w1, w2, u[19], m[20]);
+	MONT_MAC(t0, t1, t2, u[20], m[19]);
+	MONT_MAC(v0, v1, v2, u[21], m[18]);
+	MONT_MAC(w0, w1, w2, u[22], m[17]);
+	MONT_MAC(t0, t1, t2, u[23], m[16]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[15] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 40 */
+	MONT_MAC(t0, t1, t2, a[17], b[23]);
+	MONT_MUL(v0, v1, v2, a[18], b[22]);
+	MONT_MUL(w0, w1, w2, a[19], b[21]);
+	MONT_MAC(t0, t1, t2, a[20], b[20]);
+	MONT_MAC(v0, v1, v2, a[21], b[19]);
+	MONT_MAC(w0, w1, w2, a[22], b[18]);
+	MONT_MAC(t0, t1, t2, a[23], b[17]);
+	MONT_MAC(v0, v1, v2, u[17], m[23]);
+	MONT_MAC(w0, w1, w2, u[18], m[22]);
+	MONT_MAC(t0, t1, t2, u[19], m[21]);
+	MONT_MAC(v0, v1, v2, u[20], m[20]);
+	MONT_MAC(w0, w1, w2, u[21], m[19]);
+	MONT_MAC(t0, t1, t2, u[22], m[18]);
+	MONT_MAC(v0, v1, v2, u[23], m[17]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[16] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 41 */
+	MONT_MAC(t0, t1, t2, a[18], b[23]);
+	MONT_MUL(v0, v1, v2, a[19], b[22]);
+	MONT_MUL(w0, w1, w2, a[20], b[21]);
+	MONT_MAC(t0, t1, t2, a[21], b[20]);
+	MONT_MAC(v0, v1, v2, a[22], b[19]);
+	MONT_MAC(w0, w1, w2, a[23], b[18]);
+	MONT_MAC(t0, t1, t2, u[18], m[23]);
+	MONT_MAC(v0, v1, v2, u[19], m[22]);
+	MONT_MAC(w0, w1, w2, u[20], m[21]);
+	MONT_MAC(t0, t1, t2, u[21], m[20]);
+	MONT_MAC(v0, v1, v2, u[22], m[19]);
+	MONT_MAC(w0, w1, w2, u[23], m[18]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[17] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 42 */
+	MONT_MAC(t0, t1, t2, a[19], b[23]);
+	MONT_MUL(v0, v1, v2, a[20], b[22]);
+	MONT_MUL(w0, w1, w2, a[21], b[21]);
+	MONT_MAC(t0, t1, t2, a[22], b[20]);
+	MONT_MAC(v0, v1, v2, a[23], b[19]);
+	MONT_MAC(w0, w1, w2, u[19], m[23]);
+	MONT_MAC(t0, t1, t2, u[20], m[22]);
+	MONT_MAC(v0, v1, v2, u[21], m[21]);
+	MONT_MAC(w0, w1, w2, u[22], m[20]);
+	MONT_MAC(t0, t1, t2, u[23], m[19]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[18] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 43 */
+	MONT_MAC(t0, t1, t2, a[20], b[23]);
+	MONT_MUL(v0, v1, v2, a[21], b[22]);
+	MONT_MUL(w0, w1, w2, a[22], b[21]);
+	MONT_MAC(t0, t1, t2, a[23], b[20]);
+	MONT_MAC(v0, v1, v2, u[20], m[23]);
+	MONT_MAC(w0, w1, w2, u[21], m[22]);
+	MONT_MAC(t0, t1, t2, u[22], m[21]);
+	MONT_MAC(v0, v1, v2, u[23], m[20]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[19] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 44 */
+	MONT_MAC(t0, t1, t2, a[21], b[23]);
+	MONT_MUL(v0, v1, v2, a[22], b[22]);
+	MONT_MUL(w0, w1, w2, a[23], b[21]);
+	MONT_MAC(t0, t1, t2, u[21], m[23]);
+	MONT_MAC(v0, v1, v2, u[22], m[22]);
+	MONT_MAC(w0, w1, w2, u[23], m[21]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[20] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 45 */
+	MONT_MAC(t0, t1, t2, a[22], b[23]);
+	MONT_MUL(v0, v1, v2, a[23], b[22]);
+	MONT_MUL(w0, w1, w2, u[22], m[23]);
+	MONT_MAC(t0, t1, t2, u[23], m[22]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[21] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 46 */
+	MONT_MAC(t0, t1, t2, a[23], b[23]);
+	MONT_MUL(v0, v1, v2, u[23], m[23]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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_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, v0, v1, v2, w0, w1, w2, borrow, take;
+	limb_t s0, s1, s2, c0, c1, c2;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], a[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MUL(s0, s1, s2, a[0], a[1]);
+	MONT_MAC(t0, t1, t2, u[0], m[1]);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MUL(s0, s1, s2, a[0], a[2]);
+	MONT_MAC(t0, t1, t2, a[1], a[1]);
+	MONT_MUL(v0, v1, v2, u[0], m[2]);
+	MONT_MUL(w0, w1, w2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MUL(s0, s1, s2, a[0], a[3]);
+	MONT_MUL(c0, c1, c2, a[1], a[2]);
+	MONT_MAC(t0, t1, t2, u[0], m[3]);
+	MONT_MUL(v0, v1, v2, u[1], m[2]);
+	MONT_MUL(w0, w1, w2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MUL(s0, s1, s2, a[0], a[4]);
+	MONT_MUL(c0, c1, c2, a[1], a[3]);
+	MONT_MAC(t0, t1, t2, a[2], a[2]);
+	MONT_MUL(v0, v1, v2, u[0], m[4]);
+	MONT_MUL(w0, w1, w2, u[1], m[3]);
+	MONT_MAC(t0, t1, t2, u[2], m[2]);
+	MONT_MAC(v0, v1, v2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MUL(s0, s1, s2, a[0], a[5]);
+	MONT_MUL(c0, c1, c2, a[1], a[4]);
+	MONT_MAC(s0, s1, s2, a[2], a[3]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MUL(v0, v1, v2, u[1], m[4]);
+	MONT_MUL(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MUL(s0, s1, s2, a[0], a[6]);
+	MONT_MUL(c0, c1, c2, a[1], a[5]);
+	MONT_MAC(s0, s1, s2, a[2], a[4]);
+	MONT_MAC(t0, t1, t2, a[3], a[3]);
+	MONT_MUL(v0, v1, v2, u[0], m[6]);
+	MONT_MUL(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MUL(s0, s1, s2, a[0], a[7]);
+	MONT_MUL(c0, c1, c2, a[1], a[6]);
+	MONT_MAC(s0, s1, s2, a[2], a[5]);
+	MONT_MAC(c0, c1, c2, a[3], a[4]);
+	MONT_MAC(t0, t1, t2, u[0], m[7]);
+	MONT_MUL(v0, v1, v2, u[1], m[6]);
+	MONT_MUL(w0, w1, w2, u[2], m[5]);
+	MONT_MAC(t0, t1, t2, u[3], m[4]);
+	MONT_MAC(v0, v1, v2, u[4], m[3]);
+	MONT_MAC(w0, w1, w2, u[5], m[2]);
+	MONT_MAC(t0, t1, t2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MUL(s0, s1, s2, a[0], a[8]);
+	MONT_MUL(c0, c1, c2, a[1], a[7]);
+	MONT_MAC(s0, s1, s2, a[2], a[6]);
+	MONT_MAC(c0, c1, c2, a[3], a[5]);
+	MONT_MAC(t0, t1, t2, a[4], a[4]);
+	MONT_MUL(v0, v1, v2, u[0], m[8]);
+	MONT_MUL(w0, w1, w2, u[1], m[7]);
+	MONT_MAC(t0, t1, t2, u[2], m[6]);
+	MONT_MAC(v0, v1, v2, u[3], m[5]);
+	MONT_MAC(w0, w1, w2, u[4], m[4]);
+	MONT_MAC(t0, t1, t2, u[5], m[3]);
+	MONT_MAC(v0, v1, v2, u[6], m[2]);
+	MONT_MAC(w0, w1, w2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MUL(s0, s1, s2, a[0], a[9]);
+	MONT_MUL(c0, c1, c2, a[1], a[8]);
+	MONT_MAC(s0, s1, s2, a[2], a[7]);
+	MONT_MAC(c0, c1, c2, a[3], a[6]);
+	MONT_MAC(s0, s1, s2, a[4], a[5]);
+	MONT_MAC(t0, t1, t2, u[0], m[9]);
+	MONT_MUL(v0, v1, v2, u[1], m[8]);
+	MONT_MUL(w0, w1, w2, u[2], m[7]);
+	MONT_MAC(t0, t1, t2, u[3], m[6]);
+	MONT_MAC(v0, v1, v2, u[4], m[5]);
+	MONT_MAC(w0, w1, w2, u[5], m[4]);
+	MONT_MAC(t0, t1, t2, u[6], m[3]);
+	MONT_MAC(v0, v1, v2, u[7], m[2]);
+	MONT_MAC(w0, w1, w2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MUL(s0, s1, s2, a[0], a[10]);
+	MONT_MUL(c0, c1, c2, a[1], a[9]);
+	MONT_MAC(s0, s1, s2, a[2], a[8]);
+	MONT_MAC(c0, c1, c2, a[3], a[7]);
+	MONT_MAC(s0, s1, s2, a[4], a[6]);
+	MONT_MAC(t0, t1, t2, a[5], a[5]);
+	MONT_MUL(v0, v1, v2, u[0], m[10]);
+	MONT_MUL(w0, w1, w2, u[1], m[9]);
+	MONT_MAC(t0, t1, t2, u[2], m[8]);
+	MONT_MAC(v0, v1, v2, u[3], m[7]);
+	MONT_MAC(w0, w1, w2, u[4], m[6]);
+	MONT_MAC(t0, t1, t2, u[5], m[5]);
+	MONT_MAC(v0, v1, v2, u[6], m[4]);
+	MONT_MAC(w0, w1, w2, u[7], m[3]);
+	MONT_MAC(t0, t1, t2, u[8], m[2]);
+	MONT_MAC(v0, v1, v2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MUL(s0, s1, s2, a[0], a[11]);
+	MONT_MUL(c0, c1, c2, a[1], a[10]);
+	MONT_MAC(s0, s1, s2, a[2], a[9]);
+	MONT_MAC(c0, c1, c2, a[3], a[8]);
+	MONT_MAC(s0, s1, s2, a[4], a[7]);
+	MONT_MAC(c0, c1, c2, a[5], a[6]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MUL(v0, v1, v2, u[1], m[10]);
+	MONT_MUL(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MUL(s0, s1, s2, a[0], a[12]);
+	MONT_MUL(c0, c1, c2, a[1], a[11]);
+	MONT_MAC(s0, s1, s2, a[2], a[10]);
+	MONT_MAC(c0, c1, c2, a[3], a[9]);
+	MONT_MAC(s0, s1, s2, a[4], a[8]);
+	MONT_MAC(c0, c1, c2, a[5], a[7]);
+	MONT_MAC(t0, t1, t2, a[6], a[6]);
+	MONT_MUL(v0, v1, v2, u[0], m[12]);
+	MONT_MUL(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MUL(s0, s1, s2, a[0], a[13]);
+	MONT_MUL(c0, c1, c2, a[1], a[12]);
+	MONT_MAC(s0, s1, s2, a[2], a[11]);
+	MONT_MAC(c0, c1, c2, a[3], a[10]);
+	MONT_MAC(s0, s1, s2, a[4], a[9]);
+	MONT_MAC(c0, c1, c2, a[5], a[8]);
+	MONT_MAC(s0, s1, s2, a[6], a[7]);
+	MONT_MAC(t0, t1, t2, u[0], m[13]);
+	MONT_MUL(v0, v1, v2, u[1], m[12]);
+	MONT_MUL(w0, w1, w2, u[2], m[11]);
+	MONT_MAC(t0, t1, t2, u[3], m[10]);
+	MONT_MAC(v0, v1, v2, u[4], m[9]);
+	MONT_MAC(w0, w1, w2, u[5], m[8]);
+	MONT_MAC(t0, t1, t2, u[6], m[7]);
+	MONT_MAC(v0, v1, v2, u[7], m[6]);
+	MONT_MAC(w0, w1, w2, u[8], m[5]);
+	MONT_MAC(t0, t1, t2, u[9], m[4]);
+	MONT_MAC(v0, v1, v2, u[10], m[3]);
+	MONT_MAC(w0, w1, w2, u[11], m[2]);
+	MONT_MAC(t0, t1, t2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MUL(s0, s1, s2, a[0], a[14]);
+	MONT_MUL(c0, c1, c2, a[1], a[13]);
+	MONT_MAC(s0, s1, s2, a[2], a[12]);
+	MONT_MAC(c0, c1, c2, a[3], a[11]);
+	MONT_MAC(s0, s1, s2, a[4], a[10]);
+	MONT_MAC(c0, c1, c2, a[5], a[9]);
+	MONT_MAC(s0, s1, s2, a[6], a[8]);
+	MONT_MAC(t0, t1, t2, a[7], a[7]);
+	MONT_MUL(v0, v1, v2, u[0], m[14]);
+	MONT_MUL(w0, w1, w2, u[1], m[13]);
+	MONT_MAC(t0, t1, t2, u[2], m[12]);
+	MONT_MAC(v0, v1, v2, u[3], m[11]);
+	MONT_MAC(w0, w1, w2, u[4], m[10]);
+	MONT_MAC(t0, t1, t2, u[5], m[9]);
+	MONT_MAC(v0, v1, v2, u[6], m[8]);
+	MONT_MAC(w0, w1, w2, u[7], m[7]);
+	MONT_MAC(t0, t1, t2, u[8], m[6]);
+	MONT_MAC(v0, v1, v2, u[9], m[5]);
+	MONT_MAC(w0, w1, w2, u[10], m[4]);
+	MONT_MAC(t0, t1, t2, u[11], m[3]);
+	MONT_MAC(v0, v1, v2, u[12], m[2]);
+	MONT_MAC(w0, w1, w2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MUL(s0, s1, s2, a[0], a[15]);
+	MONT_MUL(c0, c1, c2, a[1], a[14]);
+	MONT_MAC(s0, s1, s2, a[2], a[13]);
+	MONT_MAC(c0, c1, c2, a[3], a[12]);
+	MONT_MAC(s0, s1, s2, a[4], a[11]);
+	MONT_MAC(c0, c1, c2, a[5], a[10]);
+	MONT_MAC(s0, s1, s2, a[6], a[9]);
+	MONT_MAC(c0, c1, c2, a[7], a[8]);
+	MONT_MAC(t0, t1, t2, u[0], m[15]);
+	MONT_MUL(v0, v1, v2, u[1], m[14]);
+	MONT_MUL(w0, w1, w2, u[2], m[13]);
+	MONT_MAC(t0, t1, t2, u[3], m[12]);
+	MONT_MAC(v0, v1, v2, u[4], m[11]);
+	MONT_MAC(w0, w1, w2, u[5], m[10]);
+	MONT_MAC(t0, t1, t2, u[6], m[9]);
+	MONT_MAC(v0, v1, v2, u[7], m[8]);
+	MONT_MAC(w0, w1, w2, u[8], m[7]);
+	MONT_MAC(t0, t1, t2, u[9], m[6]);
+	MONT_MAC(v0, v1, v2, u[10], m[5]);
+	MONT_MAC(w0, w1, w2, u[11], m[4]);
+	MONT_MAC(t0, t1, t2, u[12], m[3]);
+	MONT_MAC(v0, v1, v2, u[13], m[2]);
+	MONT_MAC(w0, w1, w2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MUL(s0, s1, s2, a[0], a[16]);
+	MONT_MUL(c0, c1, c2, a[1], a[15]);
+	MONT_MAC(s0, s1, s2, a[2], a[14]);
+	MONT_MAC(c0, c1, c2, a[3], a[13]);
+	MONT_MAC(s0, s1, s2, a[4], a[12]);
+	MONT_MAC(c0, c1, c2, a[5], a[11]);
+	MONT_MAC(s0, s1, s2, a[6], a[10]);
+	MONT_MAC(c0, c1, c2, a[7], a[9]);
+	MONT_MAC(t0, t1, t2, a[8], a[8]);
+	MONT_MUL(v0, v1, v2, u[0], m[16]);
+	MONT_MUL(w0, w1, w2, u[1], m[15]);
+	MONT_MAC(t0, t1, t2, u[2], m[14]);
+	MONT_MAC(v0, v1, v2, u[3], m[13]);
+	MONT_MAC(w0, w1, w2, u[4], m[12]);
+	MONT_MAC(t0, t1, t2, u[5], m[11]);
+	MONT_MAC(v0, v1, v2, u[6], m[10]);
+	MONT_MAC(w0, w1, w2, u[7], m[9]);
+	MONT_MAC(t0, t1, t2, u[8], m[8]);
+	MONT_MAC(v0, v1, v2, u[9], m[7]);
+	MONT_MAC(w0, w1, w2, u[10], m[6]);
+	MONT_MAC(t0, t1, t2, u[11], m[5]);
+	MONT_MAC(v0, v1, v2, u[12], m[4]);
+	MONT_MAC(w0, w1, w2, u[13], m[3]);
+	MONT_MAC(t0, t1, t2, u[14], m[2]);
+	MONT_MAC(v0, v1, v2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[16] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[16], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MUL(s0, s1, s2, a[0], a[17]);
+	MONT_MUL(c0, c1, c2, a[1], a[16]);
+	MONT_MAC(s0, s1, s2, a[2], a[15]);
+	MONT_MAC(c0, c1, c2, a[3], a[14]);
+	MONT_MAC(s0, s1, s2, a[4], a[13]);
+	MONT_MAC(c0, c1, c2, a[5], a[12]);
+	MONT_MAC(s0, s1, s2, a[6], a[11]);
+	MONT_MAC(c0, c1, c2, a[7], a[10]);
+	MONT_MAC(s0, s1, s2, a[8], a[9]);
+	MONT_MAC(t0, t1, t2, u[0], m[17]);
+	MONT_MUL(v0, v1, v2, u[1], m[16]);
+	MONT_MUL(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_MAC(v0, v1, v2, u[16], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[17] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[17], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MUL(s0, s1, s2, a[0], a[18]);
+	MONT_MUL(c0, c1, c2, a[1], a[17]);
+	MONT_MAC(s0, s1, s2, a[2], a[16]);
+	MONT_MAC(c0, c1, c2, a[3], a[15]);
+	MONT_MAC(s0, s1, s2, a[4], a[14]);
+	MONT_MAC(c0, c1, c2, a[5], a[13]);
+	MONT_MAC(s0, s1, s2, a[6], a[12]);
+	MONT_MAC(c0, c1, c2, a[7], a[11]);
+	MONT_MAC(s0, s1, s2, a[8], a[10]);
+	MONT_MAC(t0, t1, t2, a[9], a[9]);
+	MONT_MUL(v0, v1, v2, u[0], m[18]);
+	MONT_MUL(w0, w1, w2, u[1], m[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[16]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_MAC(w0, w1, w2, u[16], m[2]);
+	MONT_MAC(t0, t1, t2, u[17], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[18] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[18], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MUL(s0, s1, s2, a[0], a[19]);
+	MONT_MUL(c0, c1, c2, a[1], a[18]);
+	MONT_MAC(s0, s1, s2, a[2], a[17]);
+	MONT_MAC(c0, c1, c2, a[3], a[16]);
+	MONT_MAC(s0, s1, s2, a[4], a[15]);
+	MONT_MAC(c0, c1, c2, a[5], a[14]);
+	MONT_MAC(s0, s1, s2, a[6], a[13]);
+	MONT_MAC(c0, c1, c2, a[7], a[12]);
+	MONT_MAC(s0, s1, s2, a[8], a[11]);
+	MONT_MAC(c0, c1, c2, a[9], a[10]);
+	MONT_MAC(t0, t1, t2, u[0], m[19]);
+	MONT_MUL(v0, v1, v2, u[1], m[18]);
+	MONT_MUL(w0, w1, w2, u[2], m[17]);
+	MONT_MAC(t0, t1, t2, u[3], m[16]);
+	MONT_MAC(v0, v1, v2, u[4], m[15]);
+	MONT_MAC(w0, w1, w2, u[5], m[14]);
+	MONT_MAC(t0, t1, t2, u[6], m[13]);
+	MONT_MAC(v0, v1, v2, u[7], m[12]);
+	MONT_MAC(w0, w1, w2, u[8], m[11]);
+	MONT_MAC(t0, t1, t2, u[9], m[10]);
+	MONT_MAC(v0, v1, v2, u[10], m[9]);
+	MONT_MAC(w0, w1, w2, u[11], m[8]);
+	MONT_MAC(t0, t1, t2, u[12], m[7]);
+	MONT_MAC(v0, v1, v2, u[13], m[6]);
+	MONT_MAC(w0, w1, w2, u[14], m[5]);
+	MONT_MAC(t0, t1, t2, u[15], m[4]);
+	MONT_MAC(v0, v1, v2, u[16], m[3]);
+	MONT_MAC(w0, w1, w2, u[17], m[2]);
+	MONT_MAC(t0, t1, t2, u[18], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[19] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[19], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MUL(s0, s1, s2, a[0], a[20]);
+	MONT_MUL(c0, c1, c2, a[1], a[19]);
+	MONT_MAC(s0, s1, s2, a[2], a[18]);
+	MONT_MAC(c0, c1, c2, a[3], a[17]);
+	MONT_MAC(s0, s1, s2, a[4], a[16]);
+	MONT_MAC(c0, c1, c2, a[5], a[15]);
+	MONT_MAC(s0, s1, s2, a[6], a[14]);
+	MONT_MAC(c0, c1, c2, a[7], a[13]);
+	MONT_MAC(s0, s1, s2, a[8], a[12]);
+	MONT_MAC(c0, c1, c2, a[9], a[11]);
+	MONT_MAC(t0, t1, t2, a[10], a[10]);
+	MONT_MUL(v0, v1, v2, u[0], m[20]);
+	MONT_MUL(w0, w1, w2, u[1], m[19]);
+	MONT_MAC(t0, t1, t2, u[2], m[18]);
+	MONT_MAC(v0, v1, v2, u[3], m[17]);
+	MONT_MAC(w0, w1, w2, u[4], m[16]);
+	MONT_MAC(t0, t1, t2, u[5], m[15]);
+	MONT_MAC(v0, v1, v2, u[6], m[14]);
+	MONT_MAC(w0, w1, w2, u[7], m[13]);
+	MONT_MAC(t0, t1, t2, u[8], m[12]);
+	MONT_MAC(v0, v1, v2, u[9], m[11]);
+	MONT_MAC(w0, w1, w2, u[10], m[10]);
+	MONT_MAC(t0, t1, t2, u[11], m[9]);
+	MONT_MAC(v0, v1, v2, u[12], m[8]);
+	MONT_MAC(w0, w1, w2, u[13], m[7]);
+	MONT_MAC(t0, t1, t2, u[14], m[6]);
+	MONT_MAC(v0, v1, v2, u[15], m[5]);
+	MONT_MAC(w0, w1, w2, u[16], m[4]);
+	MONT_MAC(t0, t1, t2, u[17], m[3]);
+	MONT_MAC(v0, v1, v2, u[18], m[2]);
+	MONT_MAC(w0, w1, w2, u[19], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[20] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[20], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MUL(s0, s1, s2, a[0], a[21]);
+	MONT_MUL(c0, c1, c2, a[1], a[20]);
+	MONT_MAC(s0, s1, s2, a[2], a[19]);
+	MONT_MAC(c0, c1, c2, a[3], a[18]);
+	MONT_MAC(s0, s1, s2, a[4], a[17]);
+	MONT_MAC(c0, c1, c2, a[5], a[16]);
+	MONT_MAC(s0, s1, s2, a[6], a[15]);
+	MONT_MAC(c0, c1, c2, a[7], a[14]);
+	MONT_MAC(s0, s1, s2, a[8], a[13]);
+	MONT_MAC(c0, c1, c2, a[9], a[12]);
+	MONT_MAC(s0, s1, s2, a[10], a[11]);
+	MONT_MAC(t0, t1, t2, u[0], m[21]);
+	MONT_MUL(v0, v1, v2, u[1], m[20]);
+	MONT_MUL(w0, w1, w2, u[2], m[19]);
+	MONT_MAC(t0, t1, t2, u[3], m[18]);
+	MONT_MAC(v0, v1, v2, u[4], m[17]);
+	MONT_MAC(w0, w1, w2, u[5], m[16]);
+	MONT_MAC(t0, t1, t2, u[6], m[15]);
+	MONT_MAC(v0, v1, v2, u[7], m[14]);
+	MONT_MAC(w0, w1, w2, u[8], m[13]);
+	MONT_MAC(t0, t1, t2, u[9], m[12]);
+	MONT_MAC(v0, v1, v2, u[10], m[11]);
+	MONT_MAC(w0, w1, w2, u[11], m[10]);
+	MONT_MAC(t0, t1, t2, u[12], m[9]);
+	MONT_MAC(v0, v1, v2, u[13], m[8]);
+	MONT_MAC(w0, w1, w2, u[14], m[7]);
+	MONT_MAC(t0, t1, t2, u[15], m[6]);
+	MONT_MAC(v0, v1, v2, u[16], m[5]);
+	MONT_MAC(w0, w1, w2, u[17], m[4]);
+	MONT_MAC(t0, t1, t2, u[18], m[3]);
+	MONT_MAC(v0, v1, v2, u[19], m[2]);
+	MONT_MAC(w0, w1, w2, u[20], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[21] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[21], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MUL(s0, s1, s2, a[0], a[22]);
+	MONT_MUL(c0, c1, c2, a[1], a[21]);
+	MONT_MAC(s0, s1, s2, a[2], a[20]);
+	MONT_MAC(c0, c1, c2, a[3], a[19]);
+	MONT_MAC(s0, s1, s2, a[4], a[18]);
+	MONT_MAC(c0, c1, c2, a[5], a[17]);
+	MONT_MAC(s0, s1, s2, a[6], a[16]);
+	MONT_MAC(c0, c1, c2, a[7], a[15]);
+	MONT_MAC(s0, s1, s2, a[8], a[14]);
+	MONT_MAC(c0, c1, c2, a[9], a[13]);
+	MONT_MAC(s0, s1, s2, a[10], a[12]);
+	MONT_MAC(t0, t1, t2, a[11], a[11]);
+	MONT_MUL(v0, v1, v2, u[0], m[22]);
+	MONT_MUL(w0, w1, w2, u[1], m[21]);
+	MONT_MAC(t0, t1, t2, u[2], m[20]);
+	MONT_MAC(v0, v1, v2, u[3], m[19]);
+	MONT_MAC(w0, w1, w2, u[4], m[18]);
+	MONT_MAC(t0, t1, t2, u[5], m[17]);
+	MONT_MAC(v0, v1, v2, u[6], m[16]);
+	MONT_MAC(w0, w1, w2, u[7], m[15]);
+	MONT_MAC(t0, t1, t2, u[8], m[14]);
+	MONT_MAC(v0, v1, v2, u[9], m[13]);
+	MONT_MAC(w0, w1, w2, u[10], m[12]);
+	MONT_MAC(t0, t1, t2, u[11], m[11]);
+	MONT_MAC(v0, v1, v2, u[12], m[10]);
+	MONT_MAC(w0, w1, w2, u[13], m[9]);
+	MONT_MAC(t0, t1, t2, u[14], m[8]);
+	MONT_MAC(v0, v1, v2, u[15], m[7]);
+	MONT_MAC(w0, w1, w2, u[16], m[6]);
+	MONT_MAC(t0, t1, t2, u[17], m[5]);
+	MONT_MAC(v0, v1, v2, u[18], m[4]);
+	MONT_MAC(w0, w1, w2, u[19], m[3]);
+	MONT_MAC(t0, t1, t2, u[20], m[2]);
+	MONT_MAC(v0, v1, v2, u[21], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[22] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[22], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MUL(s0, s1, s2, a[0], a[23]);
+	MONT_MUL(c0, c1, c2, a[1], a[22]);
+	MONT_MAC(s0, s1, s2, a[2], a[21]);
+	MONT_MAC(c0, c1, c2, a[3], a[20]);
+	MONT_MAC(s0, s1, s2, a[4], a[19]);
+	MONT_MAC(c0, c1, c2, a[5], a[18]);
+	MONT_MAC(s0, s1, s2, a[6], a[17]);
+	MONT_MAC(c0, c1, c2, a[7], a[16]);
+	MONT_MAC(s0, s1, s2, a[8], a[15]);
+	MONT_MAC(c0, c1, c2, a[9], a[14]);
+	MONT_MAC(s0, s1, s2, a[10], a[13]);
+	MONT_MAC(c0, c1, c2, a[11], a[12]);
+	MONT_MAC(t0, t1, t2, u[0], m[23]);
+	MONT_MUL(v0, v1, v2, u[1], m[22]);
+	MONT_MUL(w0, w1, w2, u[2], m[21]);
+	MONT_MAC(t0, t1, t2, u[3], m[20]);
+	MONT_MAC(v0, v1, v2, u[4], m[19]);
+	MONT_MAC(w0, w1, w2, u[5], m[18]);
+	MONT_MAC(t0, t1, t2, u[6], m[17]);
+	MONT_MAC(v0, v1, v2, u[7], m[16]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_MAC(v0, v1, v2, u[16], m[7]);
+	MONT_MAC(w0, w1, w2, u[17], m[6]);
+	MONT_MAC(t0, t1, t2, u[18], m[5]);
+	MONT_MAC(v0, v1, v2, u[19], m[4]);
+	MONT_MAC(w0, w1, w2, u[20], m[3]);
+	MONT_MAC(t0, t1, t2, u[21], m[2]);
+	MONT_MAC(v0, v1, v2, u[22], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[23] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[23], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MUL(s0, s1, s2, a[1], a[23]);
+	MONT_MUL(c0, c1, c2, a[2], a[22]);
+	MONT_MAC(s0, s1, s2, a[3], a[21]);
+	MONT_MAC(c0, c1, c2, a[4], a[20]);
+	MONT_MAC(s0, s1, s2, a[5], a[19]);
+	MONT_MAC(c0, c1, c2, a[6], a[18]);
+	MONT_MAC(s0, s1, s2, a[7], a[17]);
+	MONT_MAC(c0, c1, c2, a[8], a[16]);
+	MONT_MAC(s0, s1, s2, a[9], a[15]);
+	MONT_MAC(c0, c1, c2, a[10], a[14]);
+	MONT_MAC(s0, s1, s2, a[11], a[13]);
+	MONT_MAC(t0, t1, t2, a[12], a[12]);
+	MONT_MUL(v0, v1, v2, u[1], m[23]);
+	MONT_MUL(w0, w1, w2, u[2], m[22]);
+	MONT_MAC(t0, t1, t2, u[3], m[21]);
+	MONT_MAC(v0, v1, v2, u[4], m[20]);
+	MONT_MAC(w0, w1, w2, u[5], m[19]);
+	MONT_MAC(t0, t1, t2, u[6], m[18]);
+	MONT_MAC(v0, v1, v2, u[7], m[17]);
+	MONT_MAC(w0, w1, w2, u[8], m[16]);
+	MONT_MAC(t0, t1, t2, u[9], m[15]);
+	MONT_MAC(v0, v1, v2, u[10], m[14]);
+	MONT_MAC(w0, w1, w2, u[11], m[13]);
+	MONT_MAC(t0, t1, t2, u[12], m[12]);
+	MONT_MAC(v0, v1, v2, u[13], m[11]);
+	MONT_MAC(w0, w1, w2, u[14], m[10]);
+	MONT_MAC(t0, t1, t2, u[15], m[9]);
+	MONT_MAC(v0, v1, v2, u[16], m[8]);
+	MONT_MAC(w0, w1, w2, u[17], m[7]);
+	MONT_MAC(t0, t1, t2, u[18], m[6]);
+	MONT_MAC(v0, v1, v2, u[19], m[5]);
+	MONT_MAC(w0, w1, w2, u[20], m[4]);
+	MONT_MAC(t0, t1, t2, u[21], m[3]);
+	MONT_MAC(v0, v1, v2, u[22], m[2]);
+	MONT_MAC(w0, w1, w2, u[23], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MUL(s0, s1, s2, a[2], a[23]);
+	MONT_MUL(c0, c1, c2, a[3], a[22]);
+	MONT_MAC(s0, s1, s2, a[4], a[21]);
+	MONT_MAC(c0, c1, c2, a[5], a[20]);
+	MONT_MAC(s0, s1, s2, a[6], a[19]);
+	MONT_MAC(c0, c1, c2, a[7], a[18]);
+	MONT_MAC(s0, s1, s2, a[8], a[17]);
+	MONT_MAC(c0, c1, c2, a[9], a[16]);
+	MONT_MAC(s0, s1, s2, a[10], a[15]);
+	MONT_MAC(c0, c1, c2, a[11], a[14]);
+	MONT_MAC(s0, s1, s2, a[12], a[13]);
+	MONT_MAC(t0, t1, t2, u[2], m[23]);
+	MONT_MUL(v0, v1, v2, u[3], m[22]);
+	MONT_MUL(w0, w1, w2, u[4], m[21]);
+	MONT_MAC(t0, t1, t2, u[5], m[20]);
+	MONT_MAC(v0, v1, v2, u[6], m[19]);
+	MONT_MAC(w0, w1, w2, u[7], m[18]);
+	MONT_MAC(t0, t1, t2, u[8], m[17]);
+	MONT_MAC(v0, v1, v2, u[9], m[16]);
+	MONT_MAC(w0, w1, w2, u[10], m[15]);
+	MONT_MAC(t0, t1, t2, u[11], m[14]);
+	MONT_MAC(v0, v1, v2, u[12], m[13]);
+	MONT_MAC(w0, w1, w2, u[13], m[12]);
+	MONT_MAC(t0, t1, t2, u[14], m[11]);
+	MONT_MAC(v0, v1, v2, u[15], m[10]);
+	MONT_MAC(w0, w1, w2, u[16], m[9]);
+	MONT_MAC(t0, t1, t2, u[17], m[8]);
+	MONT_MAC(v0, v1, v2, u[18], m[7]);
+	MONT_MAC(w0, w1, w2, u[19], m[6]);
+	MONT_MAC(t0, t1, t2, u[20], m[5]);
+	MONT_MAC(v0, v1, v2, u[21], m[4]);
+	MONT_MAC(w0, w1, w2, u[22], m[3]);
+	MONT_MAC(t0, t1, t2, u[23], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MUL(s0, s1, s2, a[3], a[23]);
+	MONT_MUL(c0, c1, c2, a[4], a[22]);
+	MONT_MAC(s0, s1, s2, a[5], a[21]);
+	MONT_MAC(c0, c1, c2, a[6], a[20]);
+	MONT_MAC(s0, s1, s2, a[7], a[19]);
+	MONT_MAC(c0, c1, c2, a[8], a[18]);
+	MONT_MAC(s0, s1, s2, a[9], a[17]);
+	MONT_MAC(c0, c1, c2, a[10], a[16]);
+	MONT_MAC(s0, s1, s2, a[11], a[15]);
+	MONT_MAC(c0, c1, c2, a[12], a[14]);
+	MONT_MAC(t0, t1, t2, a[13], a[13]);
+	MONT_MUL(v0, v1, v2, u[3], m[23]);
+	MONT_MUL(w0, w1, w2, u[4], m[22]);
+	MONT_MAC(t0, t1, t2, u[5], m[21]);
+	MONT_MAC(v0, v1, v2, u[6], m[20]);
+	MONT_MAC(w0, w1, w2, u[7], m[19]);
+	MONT_MAC(t0, t1, t2, u[8], m[18]);
+	MONT_MAC(v0, v1, v2, u[9], m[17]);
+	MONT_MAC(w0, w1, w2, u[10], m[16]);
+	MONT_MAC(t0, t1, t2, u[11], m[15]);
+	MONT_MAC(v0, v1, v2, u[12], m[14]);
+	MONT_MAC(w0, w1, w2, u[13], m[13]);
+	MONT_MAC(t0, t1, t2, u[14], m[12]);
+	MONT_MAC(v0, v1, v2, u[15], m[11]);
+	MONT_MAC(w0, w1, w2, u[16], m[10]);
+	MONT_MAC(t0, t1, t2, u[17], m[9]);
+	MONT_MAC(v0, v1, v2, u[18], m[8]);
+	MONT_MAC(w0, w1, w2, u[19], m[7]);
+	MONT_MAC(t0, t1, t2, u[20], m[6]);
+	MONT_MAC(v0, v1, v2, u[21], m[5]);
+	MONT_MAC(w0, w1, w2, u[22], m[4]);
+	MONT_MAC(t0, t1, t2, u[23], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MUL(s0, s1, s2, a[4], a[23]);
+	MONT_MUL(c0, c1, c2, a[5], a[22]);
+	MONT_MAC(s0, s1, s2, a[6], a[21]);
+	MONT_MAC(c0, c1, c2, a[7], a[20]);
+	MONT_MAC(s0, s1, s2, a[8], a[19]);
+	MONT_MAC(c0, c1, c2, a[9], a[18]);
+	MONT_MAC(s0, s1, s2, a[10], a[17]);
+	MONT_MAC(c0, c1, c2, a[11], a[16]);
+	MONT_MAC(s0, s1, s2, a[12], a[15]);
+	MONT_MAC(c0, c1, c2, a[13], a[14]);
+	MONT_MAC(t0, t1, t2, u[4], m[23]);
+	MONT_MUL(v0, v1, v2, u[5], m[22]);
+	MONT_MUL(w0, w1, w2, u[6], m[21]);
+	MONT_MAC(t0, t1, t2, u[7], m[20]);
+	MONT_MAC(v0, v1, v2, u[8], m[19]);
+	MONT_MAC(w0, w1, w2, u[9], m[18]);
+	MONT_MAC(t0, t1, t2, u[10], m[17]);
+	MONT_MAC(v0, v1, v2, u[11], m[16]);
+	MONT_MAC(w0, w1, w2, u[12], m[15]);
+	MONT_MAC(t0, t1, t2, u[13], m[14]);
+	MONT_MAC(v0, v1, v2, u[14], m[13]);
+	MONT_MAC(w0, w1, w2, u[15], m[12]);
+	MONT_MAC(t0, t1, t2, u[16], m[11]);
+	MONT_MAC(v0, v1, v2, u[17], m[10]);
+	MONT_MAC(w0, w1, w2, u[18], m[9]);
+	MONT_MAC(t0, t1, t2, u[19], m[8]);
+	MONT_MAC(v0, v1, v2, u[20], m[7]);
+	MONT_MAC(w0, w1, w2, u[21], m[6]);
+	MONT_MAC(t0, t1, t2, u[22], m[5]);
+	MONT_MAC(v0, v1, v2, u[23], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MUL(s0, s1, s2, a[5], a[23]);
+	MONT_MUL(c0, c1, c2, a[6], a[22]);
+	MONT_MAC(s0, s1, s2, a[7], a[21]);
+	MONT_MAC(c0, c1, c2, a[8], a[20]);
+	MONT_MAC(s0, s1, s2, a[9], a[19]);
+	MONT_MAC(c0, c1, c2, a[10], a[18]);
+	MONT_MAC(s0, s1, s2, a[11], a[17]);
+	MONT_MAC(c0, c1, c2, a[12], a[16]);
+	MONT_MAC(s0, s1, s2, a[13], a[15]);
+	MONT_MAC(t0, t1, t2, a[14], a[14]);
+	MONT_MUL(v0, v1, v2, u[5], m[23]);
+	MONT_MUL(w0, w1, w2, u[6], m[22]);
+	MONT_MAC(t0, t1, t2, u[7], m[21]);
+	MONT_MAC(v0, v1, v2, u[8], m[20]);
+	MONT_MAC(w0, w1, w2, u[9], m[19]);
+	MONT_MAC(t0, t1, t2, u[10], m[18]);
+	MONT_MAC(v0, v1, v2, u[11], m[17]);
+	MONT_MAC(w0, w1, w2, u[12], m[16]);
+	MONT_MAC(t0, t1, t2, u[13], m[15]);
+	MONT_MAC(v0, v1, v2, u[14], m[14]);
+	MONT_MAC(w0, w1, w2, u[15], m[13]);
+	MONT_MAC(t0, t1, t2, u[16], m[12]);
+	MONT_MAC(v0, v1, v2, u[17], m[11]);
+	MONT_MAC(w0, w1, w2, u[18], m[10]);
+	MONT_MAC(t0, t1, t2, u[19], m[9]);
+	MONT_MAC(v0, v1, v2, u[20], m[8]);
+	MONT_MAC(w0, w1, w2, u[21], m[7]);
+	MONT_MAC(t0, t1, t2, u[22], m[6]);
+	MONT_MAC(v0, v1, v2, u[23], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MUL(s0, s1, s2, a[6], a[23]);
+	MONT_MUL(c0, c1, c2, a[7], a[22]);
+	MONT_MAC(s0, s1, s2, a[8], a[21]);
+	MONT_MAC(c0, c1, c2, a[9], a[20]);
+	MONT_MAC(s0, s1, s2, a[10], a[19]);
+	MONT_MAC(c0, c1, c2, a[11], a[18]);
+	MONT_MAC(s0, s1, s2, a[12], a[17]);
+	MONT_MAC(c0, c1, c2, a[13], a[16]);
+	MONT_MAC(s0, s1, s2, a[14], a[15]);
+	MONT_MAC(t0, t1, t2, u[6], m[23]);
+	MONT_MUL(v0, v1, v2, u[7], m[22]);
+	MONT_MUL(w0, w1, w2, u[8], m[21]);
+	MONT_MAC(t0, t1, t2, u[9], m[20]);
+	MONT_MAC(v0, v1, v2, u[10], m[19]);
+	MONT_MAC(w0, w1, w2, u[11], m[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[17]);
+	MONT_MAC(v0, v1, v2, u[13], m[16]);
+	MONT_MAC(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_MAC(v0, v1, v2, u[16], m[13]);
+	MONT_MAC(w0, w1, w2, u[17], m[12]);
+	MONT_MAC(t0, t1, t2, u[18], m[11]);
+	MONT_MAC(v0, v1, v2, u[19], m[10]);
+	MONT_MAC(w0, w1, w2, u[20], m[9]);
+	MONT_MAC(t0, t1, t2, u[21], m[8]);
+	MONT_MAC(v0, v1, v2, u[22], m[7]);
+	MONT_MAC(w0, w1, w2, u[23], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MUL(s0, s1, s2, a[7], a[23]);
+	MONT_MUL(c0, c1, c2, a[8], a[22]);
+	MONT_MAC(s0, s1, s2, a[9], a[21]);
+	MONT_MAC(c0, c1, c2, a[10], a[20]);
+	MONT_MAC(s0, s1, s2, a[11], a[19]);
+	MONT_MAC(c0, c1, c2, a[12], a[18]);
+	MONT_MAC(s0, s1, s2, a[13], a[17]);
+	MONT_MAC(c0, c1, c2, a[14], a[16]);
+	MONT_MAC(t0, t1, t2, a[15], a[15]);
+	MONT_MUL(v0, v1, v2, u[7], m[23]);
+	MONT_MUL(w0, w1, w2, u[8], m[22]);
+	MONT_MAC(t0, t1, t2, u[9], m[21]);
+	MONT_MAC(v0, v1, v2, u[10], m[20]);
+	MONT_MAC(w0, w1, w2, u[11], m[19]);
+	MONT_MAC(t0, t1, t2, u[12], m[18]);
+	MONT_MAC(v0, v1, v2, u[13], m[17]);
+	MONT_MAC(w0, w1, w2, u[14], m[16]);
+	MONT_MAC(t0, t1, t2, u[15], m[15]);
+	MONT_MAC(v0, v1, v2, u[16], m[14]);
+	MONT_MAC(w0, w1, w2, u[17], m[13]);
+	MONT_MAC(t0, t1, t2, u[18], m[12]);
+	MONT_MAC(v0, v1, v2, u[19], m[11]);
+	MONT_MAC(w0, w1, w2, u[20], m[10]);
+	MONT_MAC(t0, t1, t2, u[21], m[9]);
+	MONT_MAC(v0, v1, v2, u[22], m[8]);
+	MONT_MAC(w0, w1, w2, u[23], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 31 */
+	MONT_MUL(s0, s1, s2, a[8], a[23]);
+	MONT_MUL(c0, c1, c2, a[9], a[22]);
+	MONT_MAC(s0, s1, s2, a[10], a[21]);
+	MONT_MAC(c0, c1, c2, a[11], a[20]);
+	MONT_MAC(s0, s1, s2, a[12], a[19]);
+	MONT_MAC(c0, c1, c2, a[13], a[18]);
+	MONT_MAC(s0, s1, s2, a[14], a[17]);
+	MONT_MAC(c0, c1, c2, a[15], a[16]);
+	MONT_MAC(t0, t1, t2, u[8], m[23]);
+	MONT_MUL(v0, v1, v2, u[9], m[22]);
+	MONT_MUL(w0, w1, w2, u[10], m[21]);
+	MONT_MAC(t0, t1, t2, u[11], m[20]);
+	MONT_MAC(v0, v1, v2, u[12], m[19]);
+	MONT_MAC(w0, w1, w2, u[13], m[18]);
+	MONT_MAC(t0, t1, t2, u[14], m[17]);
+	MONT_MAC(v0, v1, v2, u[15], m[16]);
+	MONT_MAC(w0, w1, w2, u[16], m[15]);
+	MONT_MAC(t0, t1, t2, u[17], m[14]);
+	MONT_MAC(v0, v1, v2, u[18], m[13]);
+	MONT_MAC(w0, w1, w2, u[19], m[12]);
+	MONT_MAC(t0, t1, t2, u[20], m[11]);
+	MONT_MAC(v0, v1, v2, u[21], m[10]);
+	MONT_MAC(w0, w1, w2, u[22], m[9]);
+	MONT_MAC(t0, t1, t2, u[23], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 32 */
+	MONT_MUL(s0, s1, s2, a[9], a[23]);
+	MONT_MUL(c0, c1, c2, a[10], a[22]);
+	MONT_MAC(s0, s1, s2, a[11], a[21]);
+	MONT_MAC(c0, c1, c2, a[12], a[20]);
+	MONT_MAC(s0, s1, s2, a[13], a[19]);
+	MONT_MAC(c0, c1, c2, a[14], a[18]);
+	MONT_MAC(s0, s1, s2, a[15], a[17]);
+	MONT_MAC(t0, t1, t2, a[16], a[16]);
+	MONT_MUL(v0, v1, v2, u[9], m[23]);
+	MONT_MUL(w0, w1, w2, u[10], m[22]);
+	MONT_MAC(t0, t1, t2, u[11], m[21]);
+	MONT_MAC(v0, v1, v2, u[12], m[20]);
+	MONT_MAC(w0, w1, w2, u[13], m[19]);
+	MONT_MAC(t0, t1, t2, u[14], m[18]);
+	MONT_MAC(v0, v1, v2, u[15], m[17]);
+	MONT_MAC(w0, w1, w2, u[16], m[16]);
+	MONT_MAC(t0, t1, t2, u[17], m[15]);
+	MONT_MAC(v0, v1, v2, u[18], m[14]);
+	MONT_MAC(w0, w1, w2, u[19], m[13]);
+	MONT_MAC(t0, t1, t2, u[20], m[12]);
+	MONT_MAC(v0, v1, v2, u[21], m[11]);
+	MONT_MAC(w0, w1, w2, u[22], m[10]);
+	MONT_MAC(t0, t1, t2, u[23], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 33 */
+	MONT_MUL(s0, s1, s2, a[10], a[23]);
+	MONT_MUL(c0, c1, c2, a[11], a[22]);
+	MONT_MAC(s0, s1, s2, a[12], a[21]);
+	MONT_MAC(c0, c1, c2, a[13], a[20]);
+	MONT_MAC(s0, s1, s2, a[14], a[19]);
+	MONT_MAC(c0, c1, c2, a[15], a[18]);
+	MONT_MAC(s0, s1, s2, a[16], a[17]);
+	MONT_MAC(t0, t1, t2, u[10], m[23]);
+	MONT_MUL(v0, v1, v2, u[11], m[22]);
+	MONT_MUL(w0, w1, w2, u[12], m[21]);
+	MONT_MAC(t0, t1, t2, u[13], m[20]);
+	MONT_MAC(v0, v1, v2, u[14], m[19]);
+	MONT_MAC(w0, w1, w2, u[15], m[18]);
+	MONT_MAC(t0, t1, t2, u[16], m[17]);
+	MONT_MAC(v0, v1, v2, u[17], m[16]);
+	MONT_MAC(w0, w1, w2, u[18], m[15]);
+	MONT_MAC(t0, t1, t2, u[19], m[14]);
+	MONT_MAC(v0, v1, v2, u[20], m[13]);
+	MONT_MAC(w0, w1, w2, u[21], m[12]);
+	MONT_MAC(t0, t1, t2, u[22], m[11]);
+	MONT_MAC(v0, v1, v2, u[23], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 34 */
+	MONT_MUL(s0, s1, s2, a[11], a[23]);
+	MONT_MUL(c0, c1, c2, a[12], a[22]);
+	MONT_MAC(s0, s1, s2, a[13], a[21]);
+	MONT_MAC(c0, c1, c2, a[14], a[20]);
+	MONT_MAC(s0, s1, s2, a[15], a[19]);
+	MONT_MAC(c0, c1, c2, a[16], a[18]);
+	MONT_MAC(t0, t1, t2, a[17], a[17]);
+	MONT_MUL(v0, v1, v2, u[11], m[23]);
+	MONT_MUL(w0, w1, w2, u[12], m[22]);
+	MONT_MAC(t0, t1, t2, u[13], m[21]);
+	MONT_MAC(v0, v1, v2, u[14], m[20]);
+	MONT_MAC(w0, w1, w2, u[15], m[19]);
+	MONT_MAC(t0, t1, t2, u[16], m[18]);
+	MONT_MAC(v0, v1, v2, u[17], m[17]);
+	MONT_MAC(w0, w1, w2, u[18], m[16]);
+	MONT_MAC(t0, t1, t2, u[19], m[15]);
+	MONT_MAC(v0, v1, v2, u[20], m[14]);
+	MONT_MAC(w0, w1, w2, u[21], m[13]);
+	MONT_MAC(t0, t1, t2, u[22], m[12]);
+	MONT_MAC(v0, v1, v2, u[23], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 35 */
+	MONT_MUL(s0, s1, s2, a[12], a[23]);
+	MONT_MUL(c0, c1, c2, a[13], a[22]);
+	MONT_MAC(s0, s1, s2, a[14], a[21]);
+	MONT_MAC(c0, c1, c2, a[15], a[20]);
+	MONT_MAC(s0, s1, s2, a[16], a[19]);
+	MONT_MAC(c0, c1, c2, a[17], a[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[23]);
+	MONT_MUL(v0, v1, v2, u[13], m[22]);
+	MONT_MUL(w0, w1, w2, u[14], m[21]);
+	MONT_MAC(t0, t1, t2, u[15], m[20]);
+	MONT_MAC(v0, v1, v2, u[16], m[19]);
+	MONT_MAC(w0, w1, w2, u[17], m[18]);
+	MONT_MAC(t0, t1, t2, u[18], m[17]);
+	MONT_MAC(v0, v1, v2, u[19], m[16]);
+	MONT_MAC(w0, w1, w2, u[20], m[15]);
+	MONT_MAC(t0, t1, t2, u[21], m[14]);
+	MONT_MAC(v0, v1, v2, u[22], m[13]);
+	MONT_MAC(w0, w1, w2, u[23], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 36 */
+	MONT_MUL(s0, s1, s2, a[13], a[23]);
+	MONT_MUL(c0, c1, c2, a[14], a[22]);
+	MONT_MAC(s0, s1, s2, a[15], a[21]);
+	MONT_MAC(c0, c1, c2, a[16], a[20]);
+	MONT_MAC(s0, s1, s2, a[17], a[19]);
+	MONT_MAC(t0, t1, t2, a[18], a[18]);
+	MONT_MUL(v0, v1, v2, u[13], m[23]);
+	MONT_MUL(w0, w1, w2, u[14], m[22]);
+	MONT_MAC(t0, t1, t2, u[15], m[21]);
+	MONT_MAC(v0, v1, v2, u[16], m[20]);
+	MONT_MAC(w0, w1, w2, u[17], m[19]);
+	MONT_MAC(t0, t1, t2, u[18], m[18]);
+	MONT_MAC(v0, v1, v2, u[19], m[17]);
+	MONT_MAC(w0, w1, w2, u[20], m[16]);
+	MONT_MAC(t0, t1, t2, u[21], m[15]);
+	MONT_MAC(v0, v1, v2, u[22], m[14]);
+	MONT_MAC(w0, w1, w2, u[23], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 37 */
+	MONT_MUL(s0, s1, s2, a[14], a[23]);
+	MONT_MUL(c0, c1, c2, a[15], a[22]);
+	MONT_MAC(s0, s1, s2, a[16], a[21]);
+	MONT_MAC(c0, c1, c2, a[17], a[20]);
+	MONT_MAC(s0, s1, s2, a[18], a[19]);
+	MONT_MAC(t0, t1, t2, u[14], m[23]);
+	MONT_MUL(v0, v1, v2, u[15], m[22]);
+	MONT_MUL(w0, w1, w2, u[16], m[21]);
+	MONT_MAC(t0, t1, t2, u[17], m[20]);
+	MONT_MAC(v0, v1, v2, u[18], m[19]);
+	MONT_MAC(w0, w1, w2, u[19], m[18]);
+	MONT_MAC(t0, t1, t2, u[20], m[17]);
+	MONT_MAC(v0, v1, v2, u[21], m[16]);
+	MONT_MAC(w0, w1, w2, u[22], m[15]);
+	MONT_MAC(t0, t1, t2, u[23], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 38 */
+	MONT_MUL(s0, s1, s2, a[15], a[23]);
+	MONT_MUL(c0, c1, c2, a[16], a[22]);
+	MONT_MAC(s0, s1, s2, a[17], a[21]);
+	MONT_MAC(c0, c1, c2, a[18], a[20]);
+	MONT_MAC(t0, t1, t2, a[19], a[19]);
+	MONT_MUL(v0, v1, v2, u[15], m[23]);
+	MONT_MUL(w0, w1, w2, u[16], m[22]);
+	MONT_MAC(t0, t1, t2, u[17], m[21]);
+	MONT_MAC(v0, v1, v2, u[18], m[20]);
+	MONT_MAC(w0, w1, w2, u[19], m[19]);
+	MONT_MAC(t0, t1, t2, u[20], m[18]);
+	MONT_MAC(v0, v1, v2, u[21], m[17]);
+	MONT_MAC(w0, w1, w2, u[22], m[16]);
+	MONT_MAC(t0, t1, t2, u[23], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[14] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 39 */
+	MONT_MUL(s0, s1, s2, a[16], a[23]);
+	MONT_MUL(c0, c1, c2, a[17], a[22]);
+	MONT_MAC(s0, s1, s2, a[18], a[21]);
+	MONT_MAC(c0, c1, c2, a[19], a[20]);
+	MONT_MAC(t0, t1, t2, u[16], m[23]);
+	MONT_MUL(v0, v1, v2, u[17], m[22]);
+	MONT_MUL(w0, w1, w2, u[18], m[21]);
+	MONT_MAC(t0, t1, t2, u[19], m[20]);
+	MONT_MAC(v0, v1, v2, u[20], m[19]);
+	MONT_MAC(w0, w1, w2, u[21], m[18]);
+	MONT_MAC(t0, t1, t2, u[22], m[17]);
+	MONT_MAC(v0, v1, v2, u[23], m[16]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[15] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 40 */
+	MONT_MUL(s0, s1, s2, a[17], a[23]);
+	MONT_MUL(c0, c1, c2, a[18], a[22]);
+	MONT_MAC(s0, s1, s2, a[19], a[21]);
+	MONT_MAC(t0, t1, t2, a[20], a[20]);
+	MONT_MUL(v0, v1, v2, u[17], m[23]);
+	MONT_MUL(w0, w1, w2, u[18], m[22]);
+	MONT_MAC(t0, t1, t2, u[19], m[21]);
+	MONT_MAC(v0, v1, v2, u[20], m[20]);
+	MONT_MAC(w0, w1, w2, u[21], m[19]);
+	MONT_MAC(t0, t1, t2, u[22], m[18]);
+	MONT_MAC(v0, v1, v2, u[23], m[17]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[16] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 41 */
+	MONT_MUL(s0, s1, s2, a[18], a[23]);
+	MONT_MUL(c0, c1, c2, a[19], a[22]);
+	MONT_MAC(s0, s1, s2, a[20], a[21]);
+	MONT_MAC(t0, t1, t2, u[18], m[23]);
+	MONT_MUL(v0, v1, v2, u[19], m[22]);
+	MONT_MUL(w0, w1, w2, u[20], m[21]);
+	MONT_MAC(t0, t1, t2, u[21], m[20]);
+	MONT_MAC(v0, v1, v2, u[22], m[19]);
+	MONT_MAC(w0, w1, w2, u[23], m[18]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[17] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 42 */
+	MONT_MUL(s0, s1, s2, a[19], a[23]);
+	MONT_MUL(c0, c1, c2, a[20], a[22]);
+	MONT_MAC(t0, t1, t2, a[21], a[21]);
+	MONT_MUL(v0, v1, v2, u[19], m[23]);
+	MONT_MUL(w0, w1, w2, u[20], m[22]);
+	MONT_MAC(t0, t1, t2, u[21], m[21]);
+	MONT_MAC(v0, v1, v2, u[22], m[20]);
+	MONT_MAC(w0, w1, w2, u[23], m[19]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[18] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 43 */
+	MONT_MUL(s0, s1, s2, a[20], a[23]);
+	MONT_MUL(c0, c1, c2, a[21], a[22]);
+	MONT_MAC(t0, t1, t2, u[20], m[23]);
+	MONT_MUL(v0, v1, v2, u[21], m[22]);
+	MONT_MUL(w0, w1, w2, u[22], m[21]);
+	MONT_MAC(t0, t1, t2, u[23], m[20]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[19] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 44 */
+	MONT_MUL(s0, s1, s2, a[21], a[23]);
+	MONT_MAC(t0, t1, t2, a[22], a[22]);
+	MONT_MUL(v0, v1, v2, u[21], m[23]);
+	MONT_MUL(w0, w1, w2, u[22], m[22]);
+	MONT_MAC(t0, t1, t2, u[23], m[21]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[20] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 45 */
+	MONT_MUL(s0, s1, s2, a[22], a[23]);
+	MONT_MAC(t0, t1, t2, u[22], m[23]);
+	MONT_MUL(v0, v1, v2, u[23], m[22]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[21] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 46 */
+	MONT_MAC(t0, t1, t2, a[23], a[23]);
+	MONT_MUL(v0, v1, v2, u[23], m[23]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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 * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */
+static void crypton_mont_mul32(limb_t *r, const limb_t *a, const limb_t *b,
+                               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, v0, v1, v2, w0, w1, w2, borrow, take;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], b[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MAC(t0, t1, t2, a[0], b[1]);
+	MONT_MUL(v0, v1, v2, a[1], b[0]);
+	MONT_MUL(w0, w1, w2, u[0], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MAC(t0, t1, t2, a[0], b[2]);
+	MONT_MUL(v0, v1, v2, a[1], b[1]);
+	MONT_MUL(w0, w1, w2, a[2], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[2]);
+	MONT_MAC(v0, v1, v2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MAC(t0, t1, t2, a[0], b[3]);
+	MONT_MUL(v0, v1, v2, a[1], b[2]);
+	MONT_MUL(w0, w1, w2, a[2], b[1]);
+	MONT_MAC(t0, t1, t2, a[3], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[3]);
+	MONT_MAC(w0, w1, w2, u[1], m[2]);
+	MONT_MAC(t0, t1, t2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MAC(t0, t1, t2, a[0], b[4]);
+	MONT_MUL(v0, v1, v2, a[1], b[3]);
+	MONT_MUL(w0, w1, w2, a[2], b[2]);
+	MONT_MAC(t0, t1, t2, a[3], b[1]);
+	MONT_MAC(v0, v1, v2, a[4], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[4]);
+	MONT_MAC(t0, t1, t2, u[1], m[3]);
+	MONT_MAC(v0, v1, v2, u[2], m[2]);
+	MONT_MAC(w0, w1, w2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MAC(t0, t1, t2, a[0], b[5]);
+	MONT_MUL(v0, v1, v2, a[1], b[4]);
+	MONT_MUL(w0, w1, w2, a[2], b[3]);
+	MONT_MAC(t0, t1, t2, a[3], b[2]);
+	MONT_MAC(v0, v1, v2, a[4], b[1]);
+	MONT_MAC(w0, w1, w2, a[5], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MAC(v0, v1, v2, u[1], m[4]);
+	MONT_MAC(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MAC(t0, t1, t2, a[0], b[6]);
+	MONT_MUL(v0, v1, v2, a[1], b[5]);
+	MONT_MUL(w0, w1, w2, a[2], b[4]);
+	MONT_MAC(t0, t1, t2, a[3], b[3]);
+	MONT_MAC(v0, v1, v2, a[4], b[2]);
+	MONT_MAC(w0, w1, w2, a[5], b[1]);
+	MONT_MAC(t0, t1, t2, a[6], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[6]);
+	MONT_MAC(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MAC(t0, t1, t2, a[0], b[7]);
+	MONT_MUL(v0, v1, v2, a[1], b[6]);
+	MONT_MUL(w0, w1, w2, a[2], b[5]);
+	MONT_MAC(t0, t1, t2, a[3], b[4]);
+	MONT_MAC(v0, v1, v2, a[4], b[3]);
+	MONT_MAC(w0, w1, w2, a[5], b[2]);
+	MONT_MAC(t0, t1, t2, a[6], b[1]);
+	MONT_MAC(v0, v1, v2, a[7], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[7]);
+	MONT_MAC(t0, t1, t2, u[1], m[6]);
+	MONT_MAC(v0, v1, v2, u[2], m[5]);
+	MONT_MAC(w0, w1, w2, u[3], m[4]);
+	MONT_MAC(t0, t1, t2, u[4], m[3]);
+	MONT_MAC(v0, v1, v2, u[5], m[2]);
+	MONT_MAC(w0, w1, w2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MAC(t0, t1, t2, a[0], b[8]);
+	MONT_MUL(v0, v1, v2, a[1], b[7]);
+	MONT_MUL(w0, w1, w2, a[2], b[6]);
+	MONT_MAC(t0, t1, t2, a[3], b[5]);
+	MONT_MAC(v0, v1, v2, a[4], b[4]);
+	MONT_MAC(w0, w1, w2, a[5], b[3]);
+	MONT_MAC(t0, t1, t2, a[6], b[2]);
+	MONT_MAC(v0, v1, v2, a[7], b[1]);
+	MONT_MAC(w0, w1, w2, a[8], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[8]);
+	MONT_MAC(v0, v1, v2, u[1], m[7]);
+	MONT_MAC(w0, w1, w2, u[2], m[6]);
+	MONT_MAC(t0, t1, t2, u[3], m[5]);
+	MONT_MAC(v0, v1, v2, u[4], m[4]);
+	MONT_MAC(w0, w1, w2, u[5], m[3]);
+	MONT_MAC(t0, t1, t2, u[6], m[2]);
+	MONT_MAC(v0, v1, v2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MAC(t0, t1, t2, a[0], b[9]);
+	MONT_MUL(v0, v1, v2, a[1], b[8]);
+	MONT_MUL(w0, w1, w2, a[2], b[7]);
+	MONT_MAC(t0, t1, t2, a[3], b[6]);
+	MONT_MAC(v0, v1, v2, a[4], b[5]);
+	MONT_MAC(w0, w1, w2, a[5], b[4]);
+	MONT_MAC(t0, t1, t2, a[6], b[3]);
+	MONT_MAC(v0, v1, v2, a[7], b[2]);
+	MONT_MAC(w0, w1, w2, a[8], b[1]);
+	MONT_MAC(t0, t1, t2, a[9], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[9]);
+	MONT_MAC(w0, w1, w2, u[1], m[8]);
+	MONT_MAC(t0, t1, t2, u[2], m[7]);
+	MONT_MAC(v0, v1, v2, u[3], m[6]);
+	MONT_MAC(w0, w1, w2, u[4], m[5]);
+	MONT_MAC(t0, t1, t2, u[5], m[4]);
+	MONT_MAC(v0, v1, v2, u[6], m[3]);
+	MONT_MAC(w0, w1, w2, u[7], m[2]);
+	MONT_MAC(t0, t1, t2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MAC(t0, t1, t2, a[0], b[10]);
+	MONT_MUL(v0, v1, v2, a[1], b[9]);
+	MONT_MUL(w0, w1, w2, a[2], b[8]);
+	MONT_MAC(t0, t1, t2, a[3], b[7]);
+	MONT_MAC(v0, v1, v2, a[4], b[6]);
+	MONT_MAC(w0, w1, w2, a[5], b[5]);
+	MONT_MAC(t0, t1, t2, a[6], b[4]);
+	MONT_MAC(v0, v1, v2, a[7], b[3]);
+	MONT_MAC(w0, w1, w2, a[8], b[2]);
+	MONT_MAC(t0, t1, t2, a[9], b[1]);
+	MONT_MAC(v0, v1, v2, a[10], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[10]);
+	MONT_MAC(t0, t1, t2, u[1], m[9]);
+	MONT_MAC(v0, v1, v2, u[2], m[8]);
+	MONT_MAC(w0, w1, w2, u[3], m[7]);
+	MONT_MAC(t0, t1, t2, u[4], m[6]);
+	MONT_MAC(v0, v1, v2, u[5], m[5]);
+	MONT_MAC(w0, w1, w2, u[6], m[4]);
+	MONT_MAC(t0, t1, t2, u[7], m[3]);
+	MONT_MAC(v0, v1, v2, u[8], m[2]);
+	MONT_MAC(w0, w1, w2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MAC(t0, t1, t2, a[0], b[11]);
+	MONT_MUL(v0, v1, v2, a[1], b[10]);
+	MONT_MUL(w0, w1, w2, a[2], b[9]);
+	MONT_MAC(t0, t1, t2, a[3], b[8]);
+	MONT_MAC(v0, v1, v2, a[4], b[7]);
+	MONT_MAC(w0, w1, w2, a[5], b[6]);
+	MONT_MAC(t0, t1, t2, a[6], b[5]);
+	MONT_MAC(v0, v1, v2, a[7], b[4]);
+	MONT_MAC(w0, w1, w2, a[8], b[3]);
+	MONT_MAC(t0, t1, t2, a[9], b[2]);
+	MONT_MAC(v0, v1, v2, a[10], b[1]);
+	MONT_MAC(w0, w1, w2, a[11], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MAC(v0, v1, v2, u[1], m[10]);
+	MONT_MAC(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MAC(t0, t1, t2, a[0], b[12]);
+	MONT_MUL(v0, v1, v2, a[1], b[11]);
+	MONT_MUL(w0, w1, w2, a[2], b[10]);
+	MONT_MAC(t0, t1, t2, a[3], b[9]);
+	MONT_MAC(v0, v1, v2, a[4], b[8]);
+	MONT_MAC(w0, w1, w2, a[5], b[7]);
+	MONT_MAC(t0, t1, t2, a[6], b[6]);
+	MONT_MAC(v0, v1, v2, a[7], b[5]);
+	MONT_MAC(w0, w1, w2, a[8], b[4]);
+	MONT_MAC(t0, t1, t2, a[9], b[3]);
+	MONT_MAC(v0, v1, v2, a[10], b[2]);
+	MONT_MAC(w0, w1, w2, a[11], b[1]);
+	MONT_MAC(t0, t1, t2, a[12], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[12]);
+	MONT_MAC(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MAC(t0, t1, t2, a[0], b[13]);
+	MONT_MUL(v0, v1, v2, a[1], b[12]);
+	MONT_MUL(w0, w1, w2, a[2], b[11]);
+	MONT_MAC(t0, t1, t2, a[3], b[10]);
+	MONT_MAC(v0, v1, v2, a[4], b[9]);
+	MONT_MAC(w0, w1, w2, a[5], b[8]);
+	MONT_MAC(t0, t1, t2, a[6], b[7]);
+	MONT_MAC(v0, v1, v2, a[7], b[6]);
+	MONT_MAC(w0, w1, w2, a[8], b[5]);
+	MONT_MAC(t0, t1, t2, a[9], b[4]);
+	MONT_MAC(v0, v1, v2, a[10], b[3]);
+	MONT_MAC(w0, w1, w2, a[11], b[2]);
+	MONT_MAC(t0, t1, t2, a[12], b[1]);
+	MONT_MAC(v0, v1, v2, a[13], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[13]);
+	MONT_MAC(t0, t1, t2, u[1], m[12]);
+	MONT_MAC(v0, v1, v2, u[2], m[11]);
+	MONT_MAC(w0, w1, w2, u[3], m[10]);
+	MONT_MAC(t0, t1, t2, u[4], m[9]);
+	MONT_MAC(v0, v1, v2, u[5], m[8]);
+	MONT_MAC(w0, w1, w2, u[6], m[7]);
+	MONT_MAC(t0, t1, t2, u[7], m[6]);
+	MONT_MAC(v0, v1, v2, u[8], m[5]);
+	MONT_MAC(w0, w1, w2, u[9], m[4]);
+	MONT_MAC(t0, t1, t2, u[10], m[3]);
+	MONT_MAC(v0, v1, v2, u[11], m[2]);
+	MONT_MAC(w0, w1, w2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MAC(t0, t1, t2, a[0], b[14]);
+	MONT_MUL(v0, v1, v2, a[1], b[13]);
+	MONT_MUL(w0, w1, w2, a[2], b[12]);
+	MONT_MAC(t0, t1, t2, a[3], b[11]);
+	MONT_MAC(v0, v1, v2, a[4], b[10]);
+	MONT_MAC(w0, w1, w2, a[5], b[9]);
+	MONT_MAC(t0, t1, t2, a[6], b[8]);
+	MONT_MAC(v0, v1, v2, a[7], b[7]);
+	MONT_MAC(w0, w1, w2, a[8], b[6]);
+	MONT_MAC(t0, t1, t2, a[9], b[5]);
+	MONT_MAC(v0, v1, v2, a[10], b[4]);
+	MONT_MAC(w0, w1, w2, a[11], b[3]);
+	MONT_MAC(t0, t1, t2, a[12], b[2]);
+	MONT_MAC(v0, v1, v2, a[13], b[1]);
+	MONT_MAC(w0, w1, w2, a[14], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[14]);
+	MONT_MAC(v0, v1, v2, u[1], m[13]);
+	MONT_MAC(w0, w1, w2, u[2], m[12]);
+	MONT_MAC(t0, t1, t2, u[3], m[11]);
+	MONT_MAC(v0, v1, v2, u[4], m[10]);
+	MONT_MAC(w0, w1, w2, u[5], m[9]);
+	MONT_MAC(t0, t1, t2, u[6], m[8]);
+	MONT_MAC(v0, v1, v2, u[7], m[7]);
+	MONT_MAC(w0, w1, w2, u[8], m[6]);
+	MONT_MAC(t0, t1, t2, u[9], m[5]);
+	MONT_MAC(v0, v1, v2, u[10], m[4]);
+	MONT_MAC(w0, w1, w2, u[11], m[3]);
+	MONT_MAC(t0, t1, t2, u[12], m[2]);
+	MONT_MAC(v0, v1, v2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MAC(t0, t1, t2, a[0], b[15]);
+	MONT_MUL(v0, v1, v2, a[1], b[14]);
+	MONT_MUL(w0, w1, w2, a[2], b[13]);
+	MONT_MAC(t0, t1, t2, a[3], b[12]);
+	MONT_MAC(v0, v1, v2, a[4], b[11]);
+	MONT_MAC(w0, w1, w2, a[5], b[10]);
+	MONT_MAC(t0, t1, t2, a[6], b[9]);
+	MONT_MAC(v0, v1, v2, a[7], b[8]);
+	MONT_MAC(w0, w1, w2, a[8], b[7]);
+	MONT_MAC(t0, t1, t2, a[9], b[6]);
+	MONT_MAC(v0, v1, v2, a[10], b[5]);
+	MONT_MAC(w0, w1, w2, a[11], b[4]);
+	MONT_MAC(t0, t1, t2, a[12], b[3]);
+	MONT_MAC(v0, v1, v2, a[13], b[2]);
+	MONT_MAC(w0, w1, w2, a[14], b[1]);
+	MONT_MAC(t0, t1, t2, a[15], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[15]);
+	MONT_MAC(w0, w1, w2, u[1], m[14]);
+	MONT_MAC(t0, t1, t2, u[2], m[13]);
+	MONT_MAC(v0, v1, v2, u[3], m[12]);
+	MONT_MAC(w0, w1, w2, u[4], m[11]);
+	MONT_MAC(t0, t1, t2, u[5], m[10]);
+	MONT_MAC(v0, v1, v2, u[6], m[9]);
+	MONT_MAC(w0, w1, w2, u[7], m[8]);
+	MONT_MAC(t0, t1, t2, u[8], m[7]);
+	MONT_MAC(v0, v1, v2, u[9], m[6]);
+	MONT_MAC(w0, w1, w2, u[10], m[5]);
+	MONT_MAC(t0, t1, t2, u[11], m[4]);
+	MONT_MAC(v0, v1, v2, u[12], m[3]);
+	MONT_MAC(w0, w1, w2, u[13], m[2]);
+	MONT_MAC(t0, t1, t2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MAC(t0, t1, t2, a[0], b[16]);
+	MONT_MUL(v0, v1, v2, a[1], b[15]);
+	MONT_MUL(w0, w1, w2, a[2], b[14]);
+	MONT_MAC(t0, t1, t2, a[3], b[13]);
+	MONT_MAC(v0, v1, v2, a[4], b[12]);
+	MONT_MAC(w0, w1, w2, a[5], b[11]);
+	MONT_MAC(t0, t1, t2, a[6], b[10]);
+	MONT_MAC(v0, v1, v2, a[7], b[9]);
+	MONT_MAC(w0, w1, w2, a[8], b[8]);
+	MONT_MAC(t0, t1, t2, a[9], b[7]);
+	MONT_MAC(v0, v1, v2, a[10], b[6]);
+	MONT_MAC(w0, w1, w2, a[11], b[5]);
+	MONT_MAC(t0, t1, t2, a[12], b[4]);
+	MONT_MAC(v0, v1, v2, a[13], b[3]);
+	MONT_MAC(w0, w1, w2, a[14], b[2]);
+	MONT_MAC(t0, t1, t2, a[15], b[1]);
+	MONT_MAC(v0, v1, v2, a[16], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[16]);
+	MONT_MAC(t0, t1, t2, u[1], m[15]);
+	MONT_MAC(v0, v1, v2, u[2], m[14]);
+	MONT_MAC(w0, w1, w2, u[3], m[13]);
+	MONT_MAC(t0, t1, t2, u[4], m[12]);
+	MONT_MAC(v0, v1, v2, u[5], m[11]);
+	MONT_MAC(w0, w1, w2, u[6], m[10]);
+	MONT_MAC(t0, t1, t2, u[7], m[9]);
+	MONT_MAC(v0, v1, v2, u[8], m[8]);
+	MONT_MAC(w0, w1, w2, u[9], m[7]);
+	MONT_MAC(t0, t1, t2, u[10], m[6]);
+	MONT_MAC(v0, v1, v2, u[11], m[5]);
+	MONT_MAC(w0, w1, w2, u[12], m[4]);
+	MONT_MAC(t0, t1, t2, u[13], m[3]);
+	MONT_MAC(v0, v1, v2, u[14], m[2]);
+	MONT_MAC(w0, w1, w2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[16] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[16], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MAC(t0, t1, t2, a[0], b[17]);
+	MONT_MUL(v0, v1, v2, a[1], b[16]);
+	MONT_MUL(w0, w1, w2, a[2], b[15]);
+	MONT_MAC(t0, t1, t2, a[3], b[14]);
+	MONT_MAC(v0, v1, v2, a[4], b[13]);
+	MONT_MAC(w0, w1, w2, a[5], b[12]);
+	MONT_MAC(t0, t1, t2, a[6], b[11]);
+	MONT_MAC(v0, v1, v2, a[7], b[10]);
+	MONT_MAC(w0, w1, w2, a[8], b[9]);
+	MONT_MAC(t0, t1, t2, a[9], b[8]);
+	MONT_MAC(v0, v1, v2, a[10], b[7]);
+	MONT_MAC(w0, w1, w2, a[11], b[6]);
+	MONT_MAC(t0, t1, t2, a[12], b[5]);
+	MONT_MAC(v0, v1, v2, a[13], b[4]);
+	MONT_MAC(w0, w1, w2, a[14], b[3]);
+	MONT_MAC(t0, t1, t2, a[15], b[2]);
+	MONT_MAC(v0, v1, v2, a[16], b[1]);
+	MONT_MAC(w0, w1, w2, a[17], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[17]);
+	MONT_MAC(v0, v1, v2, u[1], m[16]);
+	MONT_MAC(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_MAC(v0, v1, v2, u[16], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[17] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[17], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MAC(t0, t1, t2, a[0], b[18]);
+	MONT_MUL(v0, v1, v2, a[1], b[17]);
+	MONT_MUL(w0, w1, w2, a[2], b[16]);
+	MONT_MAC(t0, t1, t2, a[3], b[15]);
+	MONT_MAC(v0, v1, v2, a[4], b[14]);
+	MONT_MAC(w0, w1, w2, a[5], b[13]);
+	MONT_MAC(t0, t1, t2, a[6], b[12]);
+	MONT_MAC(v0, v1, v2, a[7], b[11]);
+	MONT_MAC(w0, w1, w2, a[8], b[10]);
+	MONT_MAC(t0, t1, t2, a[9], b[9]);
+	MONT_MAC(v0, v1, v2, a[10], b[8]);
+	MONT_MAC(w0, w1, w2, a[11], b[7]);
+	MONT_MAC(t0, t1, t2, a[12], b[6]);
+	MONT_MAC(v0, v1, v2, a[13], b[5]);
+	MONT_MAC(w0, w1, w2, a[14], b[4]);
+	MONT_MAC(t0, t1, t2, a[15], b[3]);
+	MONT_MAC(v0, v1, v2, a[16], b[2]);
+	MONT_MAC(w0, w1, w2, a[17], b[1]);
+	MONT_MAC(t0, t1, t2, a[18], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[18]);
+	MONT_MAC(w0, w1, w2, u[1], m[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[16]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_MAC(w0, w1, w2, u[16], m[2]);
+	MONT_MAC(t0, t1, t2, u[17], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[18] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[18], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MAC(t0, t1, t2, a[0], b[19]);
+	MONT_MUL(v0, v1, v2, a[1], b[18]);
+	MONT_MUL(w0, w1, w2, a[2], b[17]);
+	MONT_MAC(t0, t1, t2, a[3], b[16]);
+	MONT_MAC(v0, v1, v2, a[4], b[15]);
+	MONT_MAC(w0, w1, w2, a[5], b[14]);
+	MONT_MAC(t0, t1, t2, a[6], b[13]);
+	MONT_MAC(v0, v1, v2, a[7], b[12]);
+	MONT_MAC(w0, w1, w2, a[8], b[11]);
+	MONT_MAC(t0, t1, t2, a[9], b[10]);
+	MONT_MAC(v0, v1, v2, a[10], b[9]);
+	MONT_MAC(w0, w1, w2, a[11], b[8]);
+	MONT_MAC(t0, t1, t2, a[12], b[7]);
+	MONT_MAC(v0, v1, v2, a[13], b[6]);
+	MONT_MAC(w0, w1, w2, a[14], b[5]);
+	MONT_MAC(t0, t1, t2, a[15], b[4]);
+	MONT_MAC(v0, v1, v2, a[16], b[3]);
+	MONT_MAC(w0, w1, w2, a[17], b[2]);
+	MONT_MAC(t0, t1, t2, a[18], b[1]);
+	MONT_MAC(v0, v1, v2, a[19], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[19]);
+	MONT_MAC(t0, t1, t2, u[1], m[18]);
+	MONT_MAC(v0, v1, v2, u[2], m[17]);
+	MONT_MAC(w0, w1, w2, u[3], m[16]);
+	MONT_MAC(t0, t1, t2, u[4], m[15]);
+	MONT_MAC(v0, v1, v2, u[5], m[14]);
+	MONT_MAC(w0, w1, w2, u[6], m[13]);
+	MONT_MAC(t0, t1, t2, u[7], m[12]);
+	MONT_MAC(v0, v1, v2, u[8], m[11]);
+	MONT_MAC(w0, w1, w2, u[9], m[10]);
+	MONT_MAC(t0, t1, t2, u[10], m[9]);
+	MONT_MAC(v0, v1, v2, u[11], m[8]);
+	MONT_MAC(w0, w1, w2, u[12], m[7]);
+	MONT_MAC(t0, t1, t2, u[13], m[6]);
+	MONT_MAC(v0, v1, v2, u[14], m[5]);
+	MONT_MAC(w0, w1, w2, u[15], m[4]);
+	MONT_MAC(t0, t1, t2, u[16], m[3]);
+	MONT_MAC(v0, v1, v2, u[17], m[2]);
+	MONT_MAC(w0, w1, w2, u[18], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[19] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[19], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MAC(t0, t1, t2, a[0], b[20]);
+	MONT_MUL(v0, v1, v2, a[1], b[19]);
+	MONT_MUL(w0, w1, w2, a[2], b[18]);
+	MONT_MAC(t0, t1, t2, a[3], b[17]);
+	MONT_MAC(v0, v1, v2, a[4], b[16]);
+	MONT_MAC(w0, w1, w2, a[5], b[15]);
+	MONT_MAC(t0, t1, t2, a[6], b[14]);
+	MONT_MAC(v0, v1, v2, a[7], b[13]);
+	MONT_MAC(w0, w1, w2, a[8], b[12]);
+	MONT_MAC(t0, t1, t2, a[9], b[11]);
+	MONT_MAC(v0, v1, v2, a[10], b[10]);
+	MONT_MAC(w0, w1, w2, a[11], b[9]);
+	MONT_MAC(t0, t1, t2, a[12], b[8]);
+	MONT_MAC(v0, v1, v2, a[13], b[7]);
+	MONT_MAC(w0, w1, w2, a[14], b[6]);
+	MONT_MAC(t0, t1, t2, a[15], b[5]);
+	MONT_MAC(v0, v1, v2, a[16], b[4]);
+	MONT_MAC(w0, w1, w2, a[17], b[3]);
+	MONT_MAC(t0, t1, t2, a[18], b[2]);
+	MONT_MAC(v0, v1, v2, a[19], b[1]);
+	MONT_MAC(w0, w1, w2, a[20], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[20]);
+	MONT_MAC(v0, v1, v2, u[1], m[19]);
+	MONT_MAC(w0, w1, w2, u[2], m[18]);
+	MONT_MAC(t0, t1, t2, u[3], m[17]);
+	MONT_MAC(v0, v1, v2, u[4], m[16]);
+	MONT_MAC(w0, w1, w2, u[5], m[15]);
+	MONT_MAC(t0, t1, t2, u[6], m[14]);
+	MONT_MAC(v0, v1, v2, u[7], m[13]);
+	MONT_MAC(w0, w1, w2, u[8], m[12]);
+	MONT_MAC(t0, t1, t2, u[9], m[11]);
+	MONT_MAC(v0, v1, v2, u[10], m[10]);
+	MONT_MAC(w0, w1, w2, u[11], m[9]);
+	MONT_MAC(t0, t1, t2, u[12], m[8]);
+	MONT_MAC(v0, v1, v2, u[13], m[7]);
+	MONT_MAC(w0, w1, w2, u[14], m[6]);
+	MONT_MAC(t0, t1, t2, u[15], m[5]);
+	MONT_MAC(v0, v1, v2, u[16], m[4]);
+	MONT_MAC(w0, w1, w2, u[17], m[3]);
+	MONT_MAC(t0, t1, t2, u[18], m[2]);
+	MONT_MAC(v0, v1, v2, u[19], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[20] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[20], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MAC(t0, t1, t2, a[0], b[21]);
+	MONT_MUL(v0, v1, v2, a[1], b[20]);
+	MONT_MUL(w0, w1, w2, a[2], b[19]);
+	MONT_MAC(t0, t1, t2, a[3], b[18]);
+	MONT_MAC(v0, v1, v2, a[4], b[17]);
+	MONT_MAC(w0, w1, w2, a[5], b[16]);
+	MONT_MAC(t0, t1, t2, a[6], b[15]);
+	MONT_MAC(v0, v1, v2, a[7], b[14]);
+	MONT_MAC(w0, w1, w2, a[8], b[13]);
+	MONT_MAC(t0, t1, t2, a[9], b[12]);
+	MONT_MAC(v0, v1, v2, a[10], b[11]);
+	MONT_MAC(w0, w1, w2, a[11], b[10]);
+	MONT_MAC(t0, t1, t2, a[12], b[9]);
+	MONT_MAC(v0, v1, v2, a[13], b[8]);
+	MONT_MAC(w0, w1, w2, a[14], b[7]);
+	MONT_MAC(t0, t1, t2, a[15], b[6]);
+	MONT_MAC(v0, v1, v2, a[16], b[5]);
+	MONT_MAC(w0, w1, w2, a[17], b[4]);
+	MONT_MAC(t0, t1, t2, a[18], b[3]);
+	MONT_MAC(v0, v1, v2, a[19], b[2]);
+	MONT_MAC(w0, w1, w2, a[20], b[1]);
+	MONT_MAC(t0, t1, t2, a[21], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[21]);
+	MONT_MAC(w0, w1, w2, u[1], m[20]);
+	MONT_MAC(t0, t1, t2, u[2], m[19]);
+	MONT_MAC(v0, v1, v2, u[3], m[18]);
+	MONT_MAC(w0, w1, w2, u[4], m[17]);
+	MONT_MAC(t0, t1, t2, u[5], m[16]);
+	MONT_MAC(v0, v1, v2, u[6], m[15]);
+	MONT_MAC(w0, w1, w2, u[7], m[14]);
+	MONT_MAC(t0, t1, t2, u[8], m[13]);
+	MONT_MAC(v0, v1, v2, u[9], m[12]);
+	MONT_MAC(w0, w1, w2, u[10], m[11]);
+	MONT_MAC(t0, t1, t2, u[11], m[10]);
+	MONT_MAC(v0, v1, v2, u[12], m[9]);
+	MONT_MAC(w0, w1, w2, u[13], m[8]);
+	MONT_MAC(t0, t1, t2, u[14], m[7]);
+	MONT_MAC(v0, v1, v2, u[15], m[6]);
+	MONT_MAC(w0, w1, w2, u[16], m[5]);
+	MONT_MAC(t0, t1, t2, u[17], m[4]);
+	MONT_MAC(v0, v1, v2, u[18], m[3]);
+	MONT_MAC(w0, w1, w2, u[19], m[2]);
+	MONT_MAC(t0, t1, t2, u[20], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[21] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[21], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MAC(t0, t1, t2, a[0], b[22]);
+	MONT_MUL(v0, v1, v2, a[1], b[21]);
+	MONT_MUL(w0, w1, w2, a[2], b[20]);
+	MONT_MAC(t0, t1, t2, a[3], b[19]);
+	MONT_MAC(v0, v1, v2, a[4], b[18]);
+	MONT_MAC(w0, w1, w2, a[5], b[17]);
+	MONT_MAC(t0, t1, t2, a[6], b[16]);
+	MONT_MAC(v0, v1, v2, a[7], b[15]);
+	MONT_MAC(w0, w1, w2, a[8], b[14]);
+	MONT_MAC(t0, t1, t2, a[9], b[13]);
+	MONT_MAC(v0, v1, v2, a[10], b[12]);
+	MONT_MAC(w0, w1, w2, a[11], b[11]);
+	MONT_MAC(t0, t1, t2, a[12], b[10]);
+	MONT_MAC(v0, v1, v2, a[13], b[9]);
+	MONT_MAC(w0, w1, w2, a[14], b[8]);
+	MONT_MAC(t0, t1, t2, a[15], b[7]);
+	MONT_MAC(v0, v1, v2, a[16], b[6]);
+	MONT_MAC(w0, w1, w2, a[17], b[5]);
+	MONT_MAC(t0, t1, t2, a[18], b[4]);
+	MONT_MAC(v0, v1, v2, a[19], b[3]);
+	MONT_MAC(w0, w1, w2, a[20], b[2]);
+	MONT_MAC(t0, t1, t2, a[21], b[1]);
+	MONT_MAC(v0, v1, v2, a[22], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[22]);
+	MONT_MAC(t0, t1, t2, u[1], m[21]);
+	MONT_MAC(v0, v1, v2, u[2], m[20]);
+	MONT_MAC(w0, w1, w2, u[3], m[19]);
+	MONT_MAC(t0, t1, t2, u[4], m[18]);
+	MONT_MAC(v0, v1, v2, u[5], m[17]);
+	MONT_MAC(w0, w1, w2, u[6], m[16]);
+	MONT_MAC(t0, t1, t2, u[7], m[15]);
+	MONT_MAC(v0, v1, v2, u[8], m[14]);
+	MONT_MAC(w0, w1, w2, u[9], m[13]);
+	MONT_MAC(t0, t1, t2, u[10], m[12]);
+	MONT_MAC(v0, v1, v2, u[11], m[11]);
+	MONT_MAC(w0, w1, w2, u[12], m[10]);
+	MONT_MAC(t0, t1, t2, u[13], m[9]);
+	MONT_MAC(v0, v1, v2, u[14], m[8]);
+	MONT_MAC(w0, w1, w2, u[15], m[7]);
+	MONT_MAC(t0, t1, t2, u[16], m[6]);
+	MONT_MAC(v0, v1, v2, u[17], m[5]);
+	MONT_MAC(w0, w1, w2, u[18], m[4]);
+	MONT_MAC(t0, t1, t2, u[19], m[3]);
+	MONT_MAC(v0, v1, v2, u[20], m[2]);
+	MONT_MAC(w0, w1, w2, u[21], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[22] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[22], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MAC(t0, t1, t2, a[0], b[23]);
+	MONT_MUL(v0, v1, v2, a[1], b[22]);
+	MONT_MUL(w0, w1, w2, a[2], b[21]);
+	MONT_MAC(t0, t1, t2, a[3], b[20]);
+	MONT_MAC(v0, v1, v2, a[4], b[19]);
+	MONT_MAC(w0, w1, w2, a[5], b[18]);
+	MONT_MAC(t0, t1, t2, a[6], b[17]);
+	MONT_MAC(v0, v1, v2, a[7], b[16]);
+	MONT_MAC(w0, w1, w2, a[8], b[15]);
+	MONT_MAC(t0, t1, t2, a[9], b[14]);
+	MONT_MAC(v0, v1, v2, a[10], b[13]);
+	MONT_MAC(w0, w1, w2, a[11], b[12]);
+	MONT_MAC(t0, t1, t2, a[12], b[11]);
+	MONT_MAC(v0, v1, v2, a[13], b[10]);
+	MONT_MAC(w0, w1, w2, a[14], b[9]);
+	MONT_MAC(t0, t1, t2, a[15], b[8]);
+	MONT_MAC(v0, v1, v2, a[16], b[7]);
+	MONT_MAC(w0, w1, w2, a[17], b[6]);
+	MONT_MAC(t0, t1, t2, a[18], b[5]);
+	MONT_MAC(v0, v1, v2, a[19], b[4]);
+	MONT_MAC(w0, w1, w2, a[20], b[3]);
+	MONT_MAC(t0, t1, t2, a[21], b[2]);
+	MONT_MAC(v0, v1, v2, a[22], b[1]);
+	MONT_MAC(w0, w1, w2, a[23], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[23]);
+	MONT_MAC(v0, v1, v2, u[1], m[22]);
+	MONT_MAC(w0, w1, w2, u[2], m[21]);
+	MONT_MAC(t0, t1, t2, u[3], m[20]);
+	MONT_MAC(v0, v1, v2, u[4], m[19]);
+	MONT_MAC(w0, w1, w2, u[5], m[18]);
+	MONT_MAC(t0, t1, t2, u[6], m[17]);
+	MONT_MAC(v0, v1, v2, u[7], m[16]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_MAC(v0, v1, v2, u[16], m[7]);
+	MONT_MAC(w0, w1, w2, u[17], m[6]);
+	MONT_MAC(t0, t1, t2, u[18], m[5]);
+	MONT_MAC(v0, v1, v2, u[19], m[4]);
+	MONT_MAC(w0, w1, w2, u[20], m[3]);
+	MONT_MAC(t0, t1, t2, u[21], m[2]);
+	MONT_MAC(v0, v1, v2, u[22], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[23] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[23], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MAC(t0, t1, t2, a[0], b[24]);
+	MONT_MUL(v0, v1, v2, a[1], b[23]);
+	MONT_MUL(w0, w1, w2, a[2], b[22]);
+	MONT_MAC(t0, t1, t2, a[3], b[21]);
+	MONT_MAC(v0, v1, v2, a[4], b[20]);
+	MONT_MAC(w0, w1, w2, a[5], b[19]);
+	MONT_MAC(t0, t1, t2, a[6], b[18]);
+	MONT_MAC(v0, v1, v2, a[7], b[17]);
+	MONT_MAC(w0, w1, w2, a[8], b[16]);
+	MONT_MAC(t0, t1, t2, a[9], b[15]);
+	MONT_MAC(v0, v1, v2, a[10], b[14]);
+	MONT_MAC(w0, w1, w2, a[11], b[13]);
+	MONT_MAC(t0, t1, t2, a[12], b[12]);
+	MONT_MAC(v0, v1, v2, a[13], b[11]);
+	MONT_MAC(w0, w1, w2, a[14], b[10]);
+	MONT_MAC(t0, t1, t2, a[15], b[9]);
+	MONT_MAC(v0, v1, v2, a[16], b[8]);
+	MONT_MAC(w0, w1, w2, a[17], b[7]);
+	MONT_MAC(t0, t1, t2, a[18], b[6]);
+	MONT_MAC(v0, v1, v2, a[19], b[5]);
+	MONT_MAC(w0, w1, w2, a[20], b[4]);
+	MONT_MAC(t0, t1, t2, a[21], b[3]);
+	MONT_MAC(v0, v1, v2, a[22], b[2]);
+	MONT_MAC(w0, w1, w2, a[23], b[1]);
+	MONT_MAC(t0, t1, t2, a[24], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[24]);
+	MONT_MAC(w0, w1, w2, u[1], m[23]);
+	MONT_MAC(t0, t1, t2, u[2], m[22]);
+	MONT_MAC(v0, v1, v2, u[3], m[21]);
+	MONT_MAC(w0, w1, w2, u[4], m[20]);
+	MONT_MAC(t0, t1, t2, u[5], m[19]);
+	MONT_MAC(v0, v1, v2, u[6], m[18]);
+	MONT_MAC(w0, w1, w2, u[7], m[17]);
+	MONT_MAC(t0, t1, t2, u[8], m[16]);
+	MONT_MAC(v0, v1, v2, u[9], m[15]);
+	MONT_MAC(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_MAC(w0, w1, w2, u[16], m[8]);
+	MONT_MAC(t0, t1, t2, u[17], m[7]);
+	MONT_MAC(v0, v1, v2, u[18], m[6]);
+	MONT_MAC(w0, w1, w2, u[19], m[5]);
+	MONT_MAC(t0, t1, t2, u[20], m[4]);
+	MONT_MAC(v0, v1, v2, u[21], m[3]);
+	MONT_MAC(w0, w1, w2, u[22], m[2]);
+	MONT_MAC(t0, t1, t2, u[23], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[24] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[24], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MAC(t0, t1, t2, a[0], b[25]);
+	MONT_MUL(v0, v1, v2, a[1], b[24]);
+	MONT_MUL(w0, w1, w2, a[2], b[23]);
+	MONT_MAC(t0, t1, t2, a[3], b[22]);
+	MONT_MAC(v0, v1, v2, a[4], b[21]);
+	MONT_MAC(w0, w1, w2, a[5], b[20]);
+	MONT_MAC(t0, t1, t2, a[6], b[19]);
+	MONT_MAC(v0, v1, v2, a[7], b[18]);
+	MONT_MAC(w0, w1, w2, a[8], b[17]);
+	MONT_MAC(t0, t1, t2, a[9], b[16]);
+	MONT_MAC(v0, v1, v2, a[10], b[15]);
+	MONT_MAC(w0, w1, w2, a[11], b[14]);
+	MONT_MAC(t0, t1, t2, a[12], b[13]);
+	MONT_MAC(v0, v1, v2, a[13], b[12]);
+	MONT_MAC(w0, w1, w2, a[14], b[11]);
+	MONT_MAC(t0, t1, t2, a[15], b[10]);
+	MONT_MAC(v0, v1, v2, a[16], b[9]);
+	MONT_MAC(w0, w1, w2, a[17], b[8]);
+	MONT_MAC(t0, t1, t2, a[18], b[7]);
+	MONT_MAC(v0, v1, v2, a[19], b[6]);
+	MONT_MAC(w0, w1, w2, a[20], b[5]);
+	MONT_MAC(t0, t1, t2, a[21], b[4]);
+	MONT_MAC(v0, v1, v2, a[22], b[3]);
+	MONT_MAC(w0, w1, w2, a[23], b[2]);
+	MONT_MAC(t0, t1, t2, a[24], b[1]);
+	MONT_MAC(v0, v1, v2, a[25], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[25]);
+	MONT_MAC(t0, t1, t2, u[1], m[24]);
+	MONT_MAC(v0, v1, v2, u[2], m[23]);
+	MONT_MAC(w0, w1, w2, u[3], m[22]);
+	MONT_MAC(t0, t1, t2, u[4], m[21]);
+	MONT_MAC(v0, v1, v2, u[5], m[20]);
+	MONT_MAC(w0, w1, w2, u[6], m[19]);
+	MONT_MAC(t0, t1, t2, u[7], m[18]);
+	MONT_MAC(v0, v1, v2, u[8], m[17]);
+	MONT_MAC(w0, w1, w2, u[9], m[16]);
+	MONT_MAC(t0, t1, t2, u[10], m[15]);
+	MONT_MAC(v0, v1, v2, u[11], m[14]);
+	MONT_MAC(w0, w1, w2, u[12], m[13]);
+	MONT_MAC(t0, t1, t2, u[13], m[12]);
+	MONT_MAC(v0, v1, v2, u[14], m[11]);
+	MONT_MAC(w0, w1, w2, u[15], m[10]);
+	MONT_MAC(t0, t1, t2, u[16], m[9]);
+	MONT_MAC(v0, v1, v2, u[17], m[8]);
+	MONT_MAC(w0, w1, w2, u[18], m[7]);
+	MONT_MAC(t0, t1, t2, u[19], m[6]);
+	MONT_MAC(v0, v1, v2, u[20], m[5]);
+	MONT_MAC(w0, w1, w2, u[21], m[4]);
+	MONT_MAC(t0, t1, t2, u[22], m[3]);
+	MONT_MAC(v0, v1, v2, u[23], m[2]);
+	MONT_MAC(w0, w1, w2, u[24], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[25] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[25], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MAC(t0, t1, t2, a[0], b[26]);
+	MONT_MUL(v0, v1, v2, a[1], b[25]);
+	MONT_MUL(w0, w1, w2, a[2], b[24]);
+	MONT_MAC(t0, t1, t2, a[3], b[23]);
+	MONT_MAC(v0, v1, v2, a[4], b[22]);
+	MONT_MAC(w0, w1, w2, a[5], b[21]);
+	MONT_MAC(t0, t1, t2, a[6], b[20]);
+	MONT_MAC(v0, v1, v2, a[7], b[19]);
+	MONT_MAC(w0, w1, w2, a[8], b[18]);
+	MONT_MAC(t0, t1, t2, a[9], b[17]);
+	MONT_MAC(v0, v1, v2, a[10], b[16]);
+	MONT_MAC(w0, w1, w2, a[11], b[15]);
+	MONT_MAC(t0, t1, t2, a[12], b[14]);
+	MONT_MAC(v0, v1, v2, a[13], b[13]);
+	MONT_MAC(w0, w1, w2, a[14], b[12]);
+	MONT_MAC(t0, t1, t2, a[15], b[11]);
+	MONT_MAC(v0, v1, v2, a[16], b[10]);
+	MONT_MAC(w0, w1, w2, a[17], b[9]);
+	MONT_MAC(t0, t1, t2, a[18], b[8]);
+	MONT_MAC(v0, v1, v2, a[19], b[7]);
+	MONT_MAC(w0, w1, w2, a[20], b[6]);
+	MONT_MAC(t0, t1, t2, a[21], b[5]);
+	MONT_MAC(v0, v1, v2, a[22], b[4]);
+	MONT_MAC(w0, w1, w2, a[23], b[3]);
+	MONT_MAC(t0, t1, t2, a[24], b[2]);
+	MONT_MAC(v0, v1, v2, a[25], b[1]);
+	MONT_MAC(w0, w1, w2, a[26], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[26]);
+	MONT_MAC(v0, v1, v2, u[1], m[25]);
+	MONT_MAC(w0, w1, w2, u[2], m[24]);
+	MONT_MAC(t0, t1, t2, u[3], m[23]);
+	MONT_MAC(v0, v1, v2, u[4], m[22]);
+	MONT_MAC(w0, w1, w2, u[5], m[21]);
+	MONT_MAC(t0, t1, t2, u[6], m[20]);
+	MONT_MAC(v0, v1, v2, u[7], m[19]);
+	MONT_MAC(w0, w1, w2, u[8], m[18]);
+	MONT_MAC(t0, t1, t2, u[9], m[17]);
+	MONT_MAC(v0, v1, v2, u[10], m[16]);
+	MONT_MAC(w0, w1, w2, u[11], m[15]);
+	MONT_MAC(t0, t1, t2, u[12], m[14]);
+	MONT_MAC(v0, v1, v2, u[13], m[13]);
+	MONT_MAC(w0, w1, w2, u[14], m[12]);
+	MONT_MAC(t0, t1, t2, u[15], m[11]);
+	MONT_MAC(v0, v1, v2, u[16], m[10]);
+	MONT_MAC(w0, w1, w2, u[17], m[9]);
+	MONT_MAC(t0, t1, t2, u[18], m[8]);
+	MONT_MAC(v0, v1, v2, u[19], m[7]);
+	MONT_MAC(w0, w1, w2, u[20], m[6]);
+	MONT_MAC(t0, t1, t2, u[21], m[5]);
+	MONT_MAC(v0, v1, v2, u[22], m[4]);
+	MONT_MAC(w0, w1, w2, u[23], m[3]);
+	MONT_MAC(t0, t1, t2, u[24], m[2]);
+	MONT_MAC(v0, v1, v2, u[25], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[26] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[26], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MAC(t0, t1, t2, a[0], b[27]);
+	MONT_MUL(v0, v1, v2, a[1], b[26]);
+	MONT_MUL(w0, w1, w2, a[2], b[25]);
+	MONT_MAC(t0, t1, t2, a[3], b[24]);
+	MONT_MAC(v0, v1, v2, a[4], b[23]);
+	MONT_MAC(w0, w1, w2, a[5], b[22]);
+	MONT_MAC(t0, t1, t2, a[6], b[21]);
+	MONT_MAC(v0, v1, v2, a[7], b[20]);
+	MONT_MAC(w0, w1, w2, a[8], b[19]);
+	MONT_MAC(t0, t1, t2, a[9], b[18]);
+	MONT_MAC(v0, v1, v2, a[10], b[17]);
+	MONT_MAC(w0, w1, w2, a[11], b[16]);
+	MONT_MAC(t0, t1, t2, a[12], b[15]);
+	MONT_MAC(v0, v1, v2, a[13], b[14]);
+	MONT_MAC(w0, w1, w2, a[14], b[13]);
+	MONT_MAC(t0, t1, t2, a[15], b[12]);
+	MONT_MAC(v0, v1, v2, a[16], b[11]);
+	MONT_MAC(w0, w1, w2, a[17], b[10]);
+	MONT_MAC(t0, t1, t2, a[18], b[9]);
+	MONT_MAC(v0, v1, v2, a[19], b[8]);
+	MONT_MAC(w0, w1, w2, a[20], b[7]);
+	MONT_MAC(t0, t1, t2, a[21], b[6]);
+	MONT_MAC(v0, v1, v2, a[22], b[5]);
+	MONT_MAC(w0, w1, w2, a[23], b[4]);
+	MONT_MAC(t0, t1, t2, a[24], b[3]);
+	MONT_MAC(v0, v1, v2, a[25], b[2]);
+	MONT_MAC(w0, w1, w2, a[26], b[1]);
+	MONT_MAC(t0, t1, t2, a[27], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[27]);
+	MONT_MAC(w0, w1, w2, u[1], m[26]);
+	MONT_MAC(t0, t1, t2, u[2], m[25]);
+	MONT_MAC(v0, v1, v2, u[3], m[24]);
+	MONT_MAC(w0, w1, w2, u[4], m[23]);
+	MONT_MAC(t0, t1, t2, u[5], m[22]);
+	MONT_MAC(v0, v1, v2, u[6], m[21]);
+	MONT_MAC(w0, w1, w2, u[7], m[20]);
+	MONT_MAC(t0, t1, t2, u[8], m[19]);
+	MONT_MAC(v0, v1, v2, u[9], m[18]);
+	MONT_MAC(w0, w1, w2, u[10], m[17]);
+	MONT_MAC(t0, t1, t2, u[11], m[16]);
+	MONT_MAC(v0, v1, v2, u[12], m[15]);
+	MONT_MAC(w0, w1, w2, u[13], m[14]);
+	MONT_MAC(t0, t1, t2, u[14], m[13]);
+	MONT_MAC(v0, v1, v2, u[15], m[12]);
+	MONT_MAC(w0, w1, w2, u[16], m[11]);
+	MONT_MAC(t0, t1, t2, u[17], m[10]);
+	MONT_MAC(v0, v1, v2, u[18], m[9]);
+	MONT_MAC(w0, w1, w2, u[19], m[8]);
+	MONT_MAC(t0, t1, t2, u[20], m[7]);
+	MONT_MAC(v0, v1, v2, u[21], m[6]);
+	MONT_MAC(w0, w1, w2, u[22], m[5]);
+	MONT_MAC(t0, t1, t2, u[23], m[4]);
+	MONT_MAC(v0, v1, v2, u[24], m[3]);
+	MONT_MAC(w0, w1, w2, u[25], m[2]);
+	MONT_MAC(t0, t1, t2, u[26], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[27] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[27], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MAC(t0, t1, t2, a[0], b[28]);
+	MONT_MUL(v0, v1, v2, a[1], b[27]);
+	MONT_MUL(w0, w1, w2, a[2], b[26]);
+	MONT_MAC(t0, t1, t2, a[3], b[25]);
+	MONT_MAC(v0, v1, v2, a[4], b[24]);
+	MONT_MAC(w0, w1, w2, a[5], b[23]);
+	MONT_MAC(t0, t1, t2, a[6], b[22]);
+	MONT_MAC(v0, v1, v2, a[7], b[21]);
+	MONT_MAC(w0, w1, w2, a[8], b[20]);
+	MONT_MAC(t0, t1, t2, a[9], b[19]);
+	MONT_MAC(v0, v1, v2, a[10], b[18]);
+	MONT_MAC(w0, w1, w2, a[11], b[17]);
+	MONT_MAC(t0, t1, t2, a[12], b[16]);
+	MONT_MAC(v0, v1, v2, a[13], b[15]);
+	MONT_MAC(w0, w1, w2, a[14], b[14]);
+	MONT_MAC(t0, t1, t2, a[15], b[13]);
+	MONT_MAC(v0, v1, v2, a[16], b[12]);
+	MONT_MAC(w0, w1, w2, a[17], b[11]);
+	MONT_MAC(t0, t1, t2, a[18], b[10]);
+	MONT_MAC(v0, v1, v2, a[19], b[9]);
+	MONT_MAC(w0, w1, w2, a[20], b[8]);
+	MONT_MAC(t0, t1, t2, a[21], b[7]);
+	MONT_MAC(v0, v1, v2, a[22], b[6]);
+	MONT_MAC(w0, w1, w2, a[23], b[5]);
+	MONT_MAC(t0, t1, t2, a[24], b[4]);
+	MONT_MAC(v0, v1, v2, a[25], b[3]);
+	MONT_MAC(w0, w1, w2, a[26], b[2]);
+	MONT_MAC(t0, t1, t2, a[27], b[1]);
+	MONT_MAC(v0, v1, v2, a[28], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[28]);
+	MONT_MAC(t0, t1, t2, u[1], m[27]);
+	MONT_MAC(v0, v1, v2, u[2], m[26]);
+	MONT_MAC(w0, w1, w2, u[3], m[25]);
+	MONT_MAC(t0, t1, t2, u[4], m[24]);
+	MONT_MAC(v0, v1, v2, u[5], m[23]);
+	MONT_MAC(w0, w1, w2, u[6], m[22]);
+	MONT_MAC(t0, t1, t2, u[7], m[21]);
+	MONT_MAC(v0, v1, v2, u[8], m[20]);
+	MONT_MAC(w0, w1, w2, u[9], m[19]);
+	MONT_MAC(t0, t1, t2, u[10], m[18]);
+	MONT_MAC(v0, v1, v2, u[11], m[17]);
+	MONT_MAC(w0, w1, w2, u[12], m[16]);
+	MONT_MAC(t0, t1, t2, u[13], m[15]);
+	MONT_MAC(v0, v1, v2, u[14], m[14]);
+	MONT_MAC(w0, w1, w2, u[15], m[13]);
+	MONT_MAC(t0, t1, t2, u[16], m[12]);
+	MONT_MAC(v0, v1, v2, u[17], m[11]);
+	MONT_MAC(w0, w1, w2, u[18], m[10]);
+	MONT_MAC(t0, t1, t2, u[19], m[9]);
+	MONT_MAC(v0, v1, v2, u[20], m[8]);
+	MONT_MAC(w0, w1, w2, u[21], m[7]);
+	MONT_MAC(t0, t1, t2, u[22], m[6]);
+	MONT_MAC(v0, v1, v2, u[23], m[5]);
+	MONT_MAC(w0, w1, w2, u[24], m[4]);
+	MONT_MAC(t0, t1, t2, u[25], m[3]);
+	MONT_MAC(v0, v1, v2, u[26], m[2]);
+	MONT_MAC(w0, w1, w2, u[27], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[28] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[28], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MAC(t0, t1, t2, a[0], b[29]);
+	MONT_MUL(v0, v1, v2, a[1], b[28]);
+	MONT_MUL(w0, w1, w2, a[2], b[27]);
+	MONT_MAC(t0, t1, t2, a[3], b[26]);
+	MONT_MAC(v0, v1, v2, a[4], b[25]);
+	MONT_MAC(w0, w1, w2, a[5], b[24]);
+	MONT_MAC(t0, t1, t2, a[6], b[23]);
+	MONT_MAC(v0, v1, v2, a[7], b[22]);
+	MONT_MAC(w0, w1, w2, a[8], b[21]);
+	MONT_MAC(t0, t1, t2, a[9], b[20]);
+	MONT_MAC(v0, v1, v2, a[10], b[19]);
+	MONT_MAC(w0, w1, w2, a[11], b[18]);
+	MONT_MAC(t0, t1, t2, a[12], b[17]);
+	MONT_MAC(v0, v1, v2, a[13], b[16]);
+	MONT_MAC(w0, w1, w2, a[14], b[15]);
+	MONT_MAC(t0, t1, t2, a[15], b[14]);
+	MONT_MAC(v0, v1, v2, a[16], b[13]);
+	MONT_MAC(w0, w1, w2, a[17], b[12]);
+	MONT_MAC(t0, t1, t2, a[18], b[11]);
+	MONT_MAC(v0, v1, v2, a[19], b[10]);
+	MONT_MAC(w0, w1, w2, a[20], b[9]);
+	MONT_MAC(t0, t1, t2, a[21], b[8]);
+	MONT_MAC(v0, v1, v2, a[22], b[7]);
+	MONT_MAC(w0, w1, w2, a[23], b[6]);
+	MONT_MAC(t0, t1, t2, a[24], b[5]);
+	MONT_MAC(v0, v1, v2, a[25], b[4]);
+	MONT_MAC(w0, w1, w2, a[26], b[3]);
+	MONT_MAC(t0, t1, t2, a[27], b[2]);
+	MONT_MAC(v0, v1, v2, a[28], b[1]);
+	MONT_MAC(w0, w1, w2, a[29], b[0]);
+	MONT_MAC(t0, t1, t2, u[0], m[29]);
+	MONT_MAC(v0, v1, v2, u[1], m[28]);
+	MONT_MAC(w0, w1, w2, u[2], m[27]);
+	MONT_MAC(t0, t1, t2, u[3], m[26]);
+	MONT_MAC(v0, v1, v2, u[4], m[25]);
+	MONT_MAC(w0, w1, w2, u[5], m[24]);
+	MONT_MAC(t0, t1, t2, u[6], m[23]);
+	MONT_MAC(v0, v1, v2, u[7], m[22]);
+	MONT_MAC(w0, w1, w2, u[8], m[21]);
+	MONT_MAC(t0, t1, t2, u[9], m[20]);
+	MONT_MAC(v0, v1, v2, u[10], m[19]);
+	MONT_MAC(w0, w1, w2, u[11], m[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[17]);
+	MONT_MAC(v0, v1, v2, u[13], m[16]);
+	MONT_MAC(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_MAC(v0, v1, v2, u[16], m[13]);
+	MONT_MAC(w0, w1, w2, u[17], m[12]);
+	MONT_MAC(t0, t1, t2, u[18], m[11]);
+	MONT_MAC(v0, v1, v2, u[19], m[10]);
+	MONT_MAC(w0, w1, w2, u[20], m[9]);
+	MONT_MAC(t0, t1, t2, u[21], m[8]);
+	MONT_MAC(v0, v1, v2, u[22], m[7]);
+	MONT_MAC(w0, w1, w2, u[23], m[6]);
+	MONT_MAC(t0, t1, t2, u[24], m[5]);
+	MONT_MAC(v0, v1, v2, u[25], m[4]);
+	MONT_MAC(w0, w1, w2, u[26], m[3]);
+	MONT_MAC(t0, t1, t2, u[27], m[2]);
+	MONT_MAC(v0, v1, v2, u[28], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[29] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[29], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MAC(t0, t1, t2, a[0], b[30]);
+	MONT_MUL(v0, v1, v2, a[1], b[29]);
+	MONT_MUL(w0, w1, w2, a[2], b[28]);
+	MONT_MAC(t0, t1, t2, a[3], b[27]);
+	MONT_MAC(v0, v1, v2, a[4], b[26]);
+	MONT_MAC(w0, w1, w2, a[5], b[25]);
+	MONT_MAC(t0, t1, t2, a[6], b[24]);
+	MONT_MAC(v0, v1, v2, a[7], b[23]);
+	MONT_MAC(w0, w1, w2, a[8], b[22]);
+	MONT_MAC(t0, t1, t2, a[9], b[21]);
+	MONT_MAC(v0, v1, v2, a[10], b[20]);
+	MONT_MAC(w0, w1, w2, a[11], b[19]);
+	MONT_MAC(t0, t1, t2, a[12], b[18]);
+	MONT_MAC(v0, v1, v2, a[13], b[17]);
+	MONT_MAC(w0, w1, w2, a[14], b[16]);
+	MONT_MAC(t0, t1, t2, a[15], b[15]);
+	MONT_MAC(v0, v1, v2, a[16], b[14]);
+	MONT_MAC(w0, w1, w2, a[17], b[13]);
+	MONT_MAC(t0, t1, t2, a[18], b[12]);
+	MONT_MAC(v0, v1, v2, a[19], b[11]);
+	MONT_MAC(w0, w1, w2, a[20], b[10]);
+	MONT_MAC(t0, t1, t2, a[21], b[9]);
+	MONT_MAC(v0, v1, v2, a[22], b[8]);
+	MONT_MAC(w0, w1, w2, a[23], b[7]);
+	MONT_MAC(t0, t1, t2, a[24], b[6]);
+	MONT_MAC(v0, v1, v2, a[25], b[5]);
+	MONT_MAC(w0, w1, w2, a[26], b[4]);
+	MONT_MAC(t0, t1, t2, a[27], b[3]);
+	MONT_MAC(v0, v1, v2, a[28], b[2]);
+	MONT_MAC(w0, w1, w2, a[29], b[1]);
+	MONT_MAC(t0, t1, t2, a[30], b[0]);
+	MONT_MAC(v0, v1, v2, u[0], m[30]);
+	MONT_MAC(w0, w1, w2, u[1], m[29]);
+	MONT_MAC(t0, t1, t2, u[2], m[28]);
+	MONT_MAC(v0, v1, v2, u[3], m[27]);
+	MONT_MAC(w0, w1, w2, u[4], m[26]);
+	MONT_MAC(t0, t1, t2, u[5], m[25]);
+	MONT_MAC(v0, v1, v2, u[6], m[24]);
+	MONT_MAC(w0, w1, w2, u[7], m[23]);
+	MONT_MAC(t0, t1, t2, u[8], m[22]);
+	MONT_MAC(v0, v1, v2, u[9], m[21]);
+	MONT_MAC(w0, w1, w2, u[10], m[20]);
+	MONT_MAC(t0, t1, t2, u[11], m[19]);
+	MONT_MAC(v0, v1, v2, u[12], m[18]);
+	MONT_MAC(w0, w1, w2, u[13], m[17]);
+	MONT_MAC(t0, t1, t2, u[14], m[16]);
+	MONT_MAC(v0, v1, v2, u[15], m[15]);
+	MONT_MAC(w0, w1, w2, u[16], m[14]);
+	MONT_MAC(t0, t1, t2, u[17], m[13]);
+	MONT_MAC(v0, v1, v2, u[18], m[12]);
+	MONT_MAC(w0, w1, w2, u[19], m[11]);
+	MONT_MAC(t0, t1, t2, u[20], m[10]);
+	MONT_MAC(v0, v1, v2, u[21], m[9]);
+	MONT_MAC(w0, w1, w2, u[22], m[8]);
+	MONT_MAC(t0, t1, t2, u[23], m[7]);
+	MONT_MAC(v0, v1, v2, u[24], m[6]);
+	MONT_MAC(w0, w1, w2, u[25], m[5]);
+	MONT_MAC(t0, t1, t2, u[26], m[4]);
+	MONT_MAC(v0, v1, v2, u[27], m[3]);
+	MONT_MAC(w0, w1, w2, u[28], m[2]);
+	MONT_MAC(t0, t1, t2, u[29], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[30] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[30], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 31 */
+	MONT_MAC(t0, t1, t2, a[0], b[31]);
+	MONT_MUL(v0, v1, v2, a[1], b[30]);
+	MONT_MUL(w0, w1, w2, a[2], b[29]);
+	MONT_MAC(t0, t1, t2, a[3], b[28]);
+	MONT_MAC(v0, v1, v2, a[4], b[27]);
+	MONT_MAC(w0, w1, w2, a[5], b[26]);
+	MONT_MAC(t0, t1, t2, a[6], b[25]);
+	MONT_MAC(v0, v1, v2, a[7], b[24]);
+	MONT_MAC(w0, w1, w2, a[8], b[23]);
+	MONT_MAC(t0, t1, t2, a[9], b[22]);
+	MONT_MAC(v0, v1, v2, a[10], b[21]);
+	MONT_MAC(w0, w1, w2, a[11], b[20]);
+	MONT_MAC(t0, t1, t2, a[12], b[19]);
+	MONT_MAC(v0, v1, v2, a[13], b[18]);
+	MONT_MAC(w0, w1, w2, a[14], b[17]);
+	MONT_MAC(t0, t1, t2, a[15], b[16]);
+	MONT_MAC(v0, v1, v2, a[16], b[15]);
+	MONT_MAC(w0, w1, w2, a[17], b[14]);
+	MONT_MAC(t0, t1, t2, a[18], b[13]);
+	MONT_MAC(v0, v1, v2, a[19], b[12]);
+	MONT_MAC(w0, w1, w2, a[20], b[11]);
+	MONT_MAC(t0, t1, t2, a[21], b[10]);
+	MONT_MAC(v0, v1, v2, a[22], b[9]);
+	MONT_MAC(w0, w1, w2, a[23], b[8]);
+	MONT_MAC(t0, t1, t2, a[24], b[7]);
+	MONT_MAC(v0, v1, v2, a[25], b[6]);
+	MONT_MAC(w0, w1, w2, a[26], b[5]);
+	MONT_MAC(t0, t1, t2, a[27], b[4]);
+	MONT_MAC(v0, v1, v2, a[28], b[3]);
+	MONT_MAC(w0, w1, w2, a[29], b[2]);
+	MONT_MAC(t0, t1, t2, a[30], b[1]);
+	MONT_MAC(v0, v1, v2, a[31], b[0]);
+	MONT_MAC(w0, w1, w2, u[0], m[31]);
+	MONT_MAC(t0, t1, t2, u[1], m[30]);
+	MONT_MAC(v0, v1, v2, u[2], m[29]);
+	MONT_MAC(w0, w1, w2, u[3], m[28]);
+	MONT_MAC(t0, t1, t2, u[4], m[27]);
+	MONT_MAC(v0, v1, v2, u[5], m[26]);
+	MONT_MAC(w0, w1, w2, u[6], m[25]);
+	MONT_MAC(t0, t1, t2, u[7], m[24]);
+	MONT_MAC(v0, v1, v2, u[8], m[23]);
+	MONT_MAC(w0, w1, w2, u[9], m[22]);
+	MONT_MAC(t0, t1, t2, u[10], m[21]);
+	MONT_MAC(v0, v1, v2, u[11], m[20]);
+	MONT_MAC(w0, w1, w2, u[12], m[19]);
+	MONT_MAC(t0, t1, t2, u[13], m[18]);
+	MONT_MAC(v0, v1, v2, u[14], m[17]);
+	MONT_MAC(w0, w1, w2, u[15], m[16]);
+	MONT_MAC(t0, t1, t2, u[16], m[15]);
+	MONT_MAC(v0, v1, v2, u[17], m[14]);
+	MONT_MAC(w0, w1, w2, u[18], m[13]);
+	MONT_MAC(t0, t1, t2, u[19], m[12]);
+	MONT_MAC(v0, v1, v2, u[20], m[11]);
+	MONT_MAC(w0, w1, w2, u[21], m[10]);
+	MONT_MAC(t0, t1, t2, u[22], m[9]);
+	MONT_MAC(v0, v1, v2, u[23], m[8]);
+	MONT_MAC(w0, w1, w2, u[24], m[7]);
+	MONT_MAC(t0, t1, t2, u[25], m[6]);
+	MONT_MAC(v0, v1, v2, u[26], m[5]);
+	MONT_MAC(w0, w1, w2, u[27], m[4]);
+	MONT_MAC(t0, t1, t2, u[28], m[3]);
+	MONT_MAC(v0, v1, v2, u[29], m[2]);
+	MONT_MAC(w0, w1, w2, u[30], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	u[31] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[31], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 32 */
+	MONT_MAC(t0, t1, t2, a[1], b[31]);
+	MONT_MUL(v0, v1, v2, a[2], b[30]);
+	MONT_MUL(w0, w1, w2, a[3], b[29]);
+	MONT_MAC(t0, t1, t2, a[4], b[28]);
+	MONT_MAC(v0, v1, v2, a[5], b[27]);
+	MONT_MAC(w0, w1, w2, a[6], b[26]);
+	MONT_MAC(t0, t1, t2, a[7], b[25]);
+	MONT_MAC(v0, v1, v2, a[8], b[24]);
+	MONT_MAC(w0, w1, w2, a[9], b[23]);
+	MONT_MAC(t0, t1, t2, a[10], b[22]);
+	MONT_MAC(v0, v1, v2, a[11], b[21]);
+	MONT_MAC(w0, w1, w2, a[12], b[20]);
+	MONT_MAC(t0, t1, t2, a[13], b[19]);
+	MONT_MAC(v0, v1, v2, a[14], b[18]);
+	MONT_MAC(w0, w1, w2, a[15], b[17]);
+	MONT_MAC(t0, t1, t2, a[16], b[16]);
+	MONT_MAC(v0, v1, v2, a[17], b[15]);
+	MONT_MAC(w0, w1, w2, a[18], b[14]);
+	MONT_MAC(t0, t1, t2, a[19], b[13]);
+	MONT_MAC(v0, v1, v2, a[20], b[12]);
+	MONT_MAC(w0, w1, w2, a[21], b[11]);
+	MONT_MAC(t0, t1, t2, a[22], b[10]);
+	MONT_MAC(v0, v1, v2, a[23], b[9]);
+	MONT_MAC(w0, w1, w2, a[24], b[8]);
+	MONT_MAC(t0, t1, t2, a[25], b[7]);
+	MONT_MAC(v0, v1, v2, a[26], b[6]);
+	MONT_MAC(w0, w1, w2, a[27], b[5]);
+	MONT_MAC(t0, t1, t2, a[28], b[4]);
+	MONT_MAC(v0, v1, v2, a[29], b[3]);
+	MONT_MAC(w0, w1, w2, a[30], b[2]);
+	MONT_MAC(t0, t1, t2, a[31], b[1]);
+	MONT_MAC(v0, v1, v2, u[1], m[31]);
+	MONT_MAC(w0, w1, w2, u[2], m[30]);
+	MONT_MAC(t0, t1, t2, u[3], m[29]);
+	MONT_MAC(v0, v1, v2, u[4], m[28]);
+	MONT_MAC(w0, w1, w2, u[5], m[27]);
+	MONT_MAC(t0, t1, t2, u[6], m[26]);
+	MONT_MAC(v0, v1, v2, u[7], m[25]);
+	MONT_MAC(w0, w1, w2, u[8], m[24]);
+	MONT_MAC(t0, t1, t2, u[9], m[23]);
+	MONT_MAC(v0, v1, v2, u[10], m[22]);
+	MONT_MAC(w0, w1, w2, u[11], m[21]);
+	MONT_MAC(t0, t1, t2, u[12], m[20]);
+	MONT_MAC(v0, v1, v2, u[13], m[19]);
+	MONT_MAC(w0, w1, w2, u[14], m[18]);
+	MONT_MAC(t0, t1, t2, u[15], m[17]);
+	MONT_MAC(v0, v1, v2, u[16], m[16]);
+	MONT_MAC(w0, w1, w2, u[17], m[15]);
+	MONT_MAC(t0, t1, t2, u[18], m[14]);
+	MONT_MAC(v0, v1, v2, u[19], m[13]);
+	MONT_MAC(w0, w1, w2, u[20], m[12]);
+	MONT_MAC(t0, t1, t2, u[21], m[11]);
+	MONT_MAC(v0, v1, v2, u[22], m[10]);
+	MONT_MAC(w0, w1, w2, u[23], m[9]);
+	MONT_MAC(t0, t1, t2, u[24], m[8]);
+	MONT_MAC(v0, v1, v2, u[25], m[7]);
+	MONT_MAC(w0, w1, w2, u[26], m[6]);
+	MONT_MAC(t0, t1, t2, u[27], m[5]);
+	MONT_MAC(v0, v1, v2, u[28], m[4]);
+	MONT_MAC(w0, w1, w2, u[29], m[3]);
+	MONT_MAC(t0, t1, t2, u[30], m[2]);
+	MONT_MAC(v0, v1, v2, u[31], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 33 */
+	MONT_MAC(t0, t1, t2, a[2], b[31]);
+	MONT_MUL(v0, v1, v2, a[3], b[30]);
+	MONT_MUL(w0, w1, w2, a[4], b[29]);
+	MONT_MAC(t0, t1, t2, a[5], b[28]);
+	MONT_MAC(v0, v1, v2, a[6], b[27]);
+	MONT_MAC(w0, w1, w2, a[7], b[26]);
+	MONT_MAC(t0, t1, t2, a[8], b[25]);
+	MONT_MAC(v0, v1, v2, a[9], b[24]);
+	MONT_MAC(w0, w1, w2, a[10], b[23]);
+	MONT_MAC(t0, t1, t2, a[11], b[22]);
+	MONT_MAC(v0, v1, v2, a[12], b[21]);
+	MONT_MAC(w0, w1, w2, a[13], b[20]);
+	MONT_MAC(t0, t1, t2, a[14], b[19]);
+	MONT_MAC(v0, v1, v2, a[15], b[18]);
+	MONT_MAC(w0, w1, w2, a[16], b[17]);
+	MONT_MAC(t0, t1, t2, a[17], b[16]);
+	MONT_MAC(v0, v1, v2, a[18], b[15]);
+	MONT_MAC(w0, w1, w2, a[19], b[14]);
+	MONT_MAC(t0, t1, t2, a[20], b[13]);
+	MONT_MAC(v0, v1, v2, a[21], b[12]);
+	MONT_MAC(w0, w1, w2, a[22], b[11]);
+	MONT_MAC(t0, t1, t2, a[23], b[10]);
+	MONT_MAC(v0, v1, v2, a[24], b[9]);
+	MONT_MAC(w0, w1, w2, a[25], b[8]);
+	MONT_MAC(t0, t1, t2, a[26], b[7]);
+	MONT_MAC(v0, v1, v2, a[27], b[6]);
+	MONT_MAC(w0, w1, w2, a[28], b[5]);
+	MONT_MAC(t0, t1, t2, a[29], b[4]);
+	MONT_MAC(v0, v1, v2, a[30], b[3]);
+	MONT_MAC(w0, w1, w2, a[31], b[2]);
+	MONT_MAC(t0, t1, t2, u[2], m[31]);
+	MONT_MAC(v0, v1, v2, u[3], m[30]);
+	MONT_MAC(w0, w1, w2, u[4], m[29]);
+	MONT_MAC(t0, t1, t2, u[5], m[28]);
+	MONT_MAC(v0, v1, v2, u[6], m[27]);
+	MONT_MAC(w0, w1, w2, u[7], m[26]);
+	MONT_MAC(t0, t1, t2, u[8], m[25]);
+	MONT_MAC(v0, v1, v2, u[9], m[24]);
+	MONT_MAC(w0, w1, w2, u[10], m[23]);
+	MONT_MAC(t0, t1, t2, u[11], m[22]);
+	MONT_MAC(v0, v1, v2, u[12], m[21]);
+	MONT_MAC(w0, w1, w2, u[13], m[20]);
+	MONT_MAC(t0, t1, t2, u[14], m[19]);
+	MONT_MAC(v0, v1, v2, u[15], m[18]);
+	MONT_MAC(w0, w1, w2, u[16], m[17]);
+	MONT_MAC(t0, t1, t2, u[17], m[16]);
+	MONT_MAC(v0, v1, v2, u[18], m[15]);
+	MONT_MAC(w0, w1, w2, u[19], m[14]);
+	MONT_MAC(t0, t1, t2, u[20], m[13]);
+	MONT_MAC(v0, v1, v2, u[21], m[12]);
+	MONT_MAC(w0, w1, w2, u[22], m[11]);
+	MONT_MAC(t0, t1, t2, u[23], m[10]);
+	MONT_MAC(v0, v1, v2, u[24], m[9]);
+	MONT_MAC(w0, w1, w2, u[25], m[8]);
+	MONT_MAC(t0, t1, t2, u[26], m[7]);
+	MONT_MAC(v0, v1, v2, u[27], m[6]);
+	MONT_MAC(w0, w1, w2, u[28], m[5]);
+	MONT_MAC(t0, t1, t2, u[29], m[4]);
+	MONT_MAC(v0, v1, v2, u[30], m[3]);
+	MONT_MAC(w0, w1, w2, u[31], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 34 */
+	MONT_MAC(t0, t1, t2, a[3], b[31]);
+	MONT_MUL(v0, v1, v2, a[4], b[30]);
+	MONT_MUL(w0, w1, w2, a[5], b[29]);
+	MONT_MAC(t0, t1, t2, a[6], b[28]);
+	MONT_MAC(v0, v1, v2, a[7], b[27]);
+	MONT_MAC(w0, w1, w2, a[8], b[26]);
+	MONT_MAC(t0, t1, t2, a[9], b[25]);
+	MONT_MAC(v0, v1, v2, a[10], b[24]);
+	MONT_MAC(w0, w1, w2, a[11], b[23]);
+	MONT_MAC(t0, t1, t2, a[12], b[22]);
+	MONT_MAC(v0, v1, v2, a[13], b[21]);
+	MONT_MAC(w0, w1, w2, a[14], b[20]);
+	MONT_MAC(t0, t1, t2, a[15], b[19]);
+	MONT_MAC(v0, v1, v2, a[16], b[18]);
+	MONT_MAC(w0, w1, w2, a[17], b[17]);
+	MONT_MAC(t0, t1, t2, a[18], b[16]);
+	MONT_MAC(v0, v1, v2, a[19], b[15]);
+	MONT_MAC(w0, w1, w2, a[20], b[14]);
+	MONT_MAC(t0, t1, t2, a[21], b[13]);
+	MONT_MAC(v0, v1, v2, a[22], b[12]);
+	MONT_MAC(w0, w1, w2, a[23], b[11]);
+	MONT_MAC(t0, t1, t2, a[24], b[10]);
+	MONT_MAC(v0, v1, v2, a[25], b[9]);
+	MONT_MAC(w0, w1, w2, a[26], b[8]);
+	MONT_MAC(t0, t1, t2, a[27], b[7]);
+	MONT_MAC(v0, v1, v2, a[28], b[6]);
+	MONT_MAC(w0, w1, w2, a[29], b[5]);
+	MONT_MAC(t0, t1, t2, a[30], b[4]);
+	MONT_MAC(v0, v1, v2, a[31], b[3]);
+	MONT_MAC(w0, w1, w2, u[3], m[31]);
+	MONT_MAC(t0, t1, t2, u[4], m[30]);
+	MONT_MAC(v0, v1, v2, u[5], m[29]);
+	MONT_MAC(w0, w1, w2, u[6], m[28]);
+	MONT_MAC(t0, t1, t2, u[7], m[27]);
+	MONT_MAC(v0, v1, v2, u[8], m[26]);
+	MONT_MAC(w0, w1, w2, u[9], m[25]);
+	MONT_MAC(t0, t1, t2, u[10], m[24]);
+	MONT_MAC(v0, v1, v2, u[11], m[23]);
+	MONT_MAC(w0, w1, w2, u[12], m[22]);
+	MONT_MAC(t0, t1, t2, u[13], m[21]);
+	MONT_MAC(v0, v1, v2, u[14], m[20]);
+	MONT_MAC(w0, w1, w2, u[15], m[19]);
+	MONT_MAC(t0, t1, t2, u[16], m[18]);
+	MONT_MAC(v0, v1, v2, u[17], m[17]);
+	MONT_MAC(w0, w1, w2, u[18], m[16]);
+	MONT_MAC(t0, t1, t2, u[19], m[15]);
+	MONT_MAC(v0, v1, v2, u[20], m[14]);
+	MONT_MAC(w0, w1, w2, u[21], m[13]);
+	MONT_MAC(t0, t1, t2, u[22], m[12]);
+	MONT_MAC(v0, v1, v2, u[23], m[11]);
+	MONT_MAC(w0, w1, w2, u[24], m[10]);
+	MONT_MAC(t0, t1, t2, u[25], m[9]);
+	MONT_MAC(v0, v1, v2, u[26], m[8]);
+	MONT_MAC(w0, w1, w2, u[27], m[7]);
+	MONT_MAC(t0, t1, t2, u[28], m[6]);
+	MONT_MAC(v0, v1, v2, u[29], m[5]);
+	MONT_MAC(w0, w1, w2, u[30], m[4]);
+	MONT_MAC(t0, t1, t2, u[31], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 35 */
+	MONT_MAC(t0, t1, t2, a[4], b[31]);
+	MONT_MUL(v0, v1, v2, a[5], b[30]);
+	MONT_MUL(w0, w1, w2, a[6], b[29]);
+	MONT_MAC(t0, t1, t2, a[7], b[28]);
+	MONT_MAC(v0, v1, v2, a[8], b[27]);
+	MONT_MAC(w0, w1, w2, a[9], b[26]);
+	MONT_MAC(t0, t1, t2, a[10], b[25]);
+	MONT_MAC(v0, v1, v2, a[11], b[24]);
+	MONT_MAC(w0, w1, w2, a[12], b[23]);
+	MONT_MAC(t0, t1, t2, a[13], b[22]);
+	MONT_MAC(v0, v1, v2, a[14], b[21]);
+	MONT_MAC(w0, w1, w2, a[15], b[20]);
+	MONT_MAC(t0, t1, t2, a[16], b[19]);
+	MONT_MAC(v0, v1, v2, a[17], b[18]);
+	MONT_MAC(w0, w1, w2, a[18], b[17]);
+	MONT_MAC(t0, t1, t2, a[19], b[16]);
+	MONT_MAC(v0, v1, v2, a[20], b[15]);
+	MONT_MAC(w0, w1, w2, a[21], b[14]);
+	MONT_MAC(t0, t1, t2, a[22], b[13]);
+	MONT_MAC(v0, v1, v2, a[23], b[12]);
+	MONT_MAC(w0, w1, w2, a[24], b[11]);
+	MONT_MAC(t0, t1, t2, a[25], b[10]);
+	MONT_MAC(v0, v1, v2, a[26], b[9]);
+	MONT_MAC(w0, w1, w2, a[27], b[8]);
+	MONT_MAC(t0, t1, t2, a[28], b[7]);
+	MONT_MAC(v0, v1, v2, a[29], b[6]);
+	MONT_MAC(w0, w1, w2, a[30], b[5]);
+	MONT_MAC(t0, t1, t2, a[31], b[4]);
+	MONT_MAC(v0, v1, v2, u[4], m[31]);
+	MONT_MAC(w0, w1, w2, u[5], m[30]);
+	MONT_MAC(t0, t1, t2, u[6], m[29]);
+	MONT_MAC(v0, v1, v2, u[7], m[28]);
+	MONT_MAC(w0, w1, w2, u[8], m[27]);
+	MONT_MAC(t0, t1, t2, u[9], m[26]);
+	MONT_MAC(v0, v1, v2, u[10], m[25]);
+	MONT_MAC(w0, w1, w2, u[11], m[24]);
+	MONT_MAC(t0, t1, t2, u[12], m[23]);
+	MONT_MAC(v0, v1, v2, u[13], m[22]);
+	MONT_MAC(w0, w1, w2, u[14], m[21]);
+	MONT_MAC(t0, t1, t2, u[15], m[20]);
+	MONT_MAC(v0, v1, v2, u[16], m[19]);
+	MONT_MAC(w0, w1, w2, u[17], m[18]);
+	MONT_MAC(t0, t1, t2, u[18], m[17]);
+	MONT_MAC(v0, v1, v2, u[19], m[16]);
+	MONT_MAC(w0, w1, w2, u[20], m[15]);
+	MONT_MAC(t0, t1, t2, u[21], m[14]);
+	MONT_MAC(v0, v1, v2, u[22], m[13]);
+	MONT_MAC(w0, w1, w2, u[23], m[12]);
+	MONT_MAC(t0, t1, t2, u[24], m[11]);
+	MONT_MAC(v0, v1, v2, u[25], m[10]);
+	MONT_MAC(w0, w1, w2, u[26], m[9]);
+	MONT_MAC(t0, t1, t2, u[27], m[8]);
+	MONT_MAC(v0, v1, v2, u[28], m[7]);
+	MONT_MAC(w0, w1, w2, u[29], m[6]);
+	MONT_MAC(t0, t1, t2, u[30], m[5]);
+	MONT_MAC(v0, v1, v2, u[31], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 36 */
+	MONT_MAC(t0, t1, t2, a[5], b[31]);
+	MONT_MUL(v0, v1, v2, a[6], b[30]);
+	MONT_MUL(w0, w1, w2, a[7], b[29]);
+	MONT_MAC(t0, t1, t2, a[8], b[28]);
+	MONT_MAC(v0, v1, v2, a[9], b[27]);
+	MONT_MAC(w0, w1, w2, a[10], b[26]);
+	MONT_MAC(t0, t1, t2, a[11], b[25]);
+	MONT_MAC(v0, v1, v2, a[12], b[24]);
+	MONT_MAC(w0, w1, w2, a[13], b[23]);
+	MONT_MAC(t0, t1, t2, a[14], b[22]);
+	MONT_MAC(v0, v1, v2, a[15], b[21]);
+	MONT_MAC(w0, w1, w2, a[16], b[20]);
+	MONT_MAC(t0, t1, t2, a[17], b[19]);
+	MONT_MAC(v0, v1, v2, a[18], b[18]);
+	MONT_MAC(w0, w1, w2, a[19], b[17]);
+	MONT_MAC(t0, t1, t2, a[20], b[16]);
+	MONT_MAC(v0, v1, v2, a[21], b[15]);
+	MONT_MAC(w0, w1, w2, a[22], b[14]);
+	MONT_MAC(t0, t1, t2, a[23], b[13]);
+	MONT_MAC(v0, v1, v2, a[24], b[12]);
+	MONT_MAC(w0, w1, w2, a[25], b[11]);
+	MONT_MAC(t0, t1, t2, a[26], b[10]);
+	MONT_MAC(v0, v1, v2, a[27], b[9]);
+	MONT_MAC(w0, w1, w2, a[28], b[8]);
+	MONT_MAC(t0, t1, t2, a[29], b[7]);
+	MONT_MAC(v0, v1, v2, a[30], b[6]);
+	MONT_MAC(w0, w1, w2, a[31], b[5]);
+	MONT_MAC(t0, t1, t2, u[5], m[31]);
+	MONT_MAC(v0, v1, v2, u[6], m[30]);
+	MONT_MAC(w0, w1, w2, u[7], m[29]);
+	MONT_MAC(t0, t1, t2, u[8], m[28]);
+	MONT_MAC(v0, v1, v2, u[9], m[27]);
+	MONT_MAC(w0, w1, w2, u[10], m[26]);
+	MONT_MAC(t0, t1, t2, u[11], m[25]);
+	MONT_MAC(v0, v1, v2, u[12], m[24]);
+	MONT_MAC(w0, w1, w2, u[13], m[23]);
+	MONT_MAC(t0, t1, t2, u[14], m[22]);
+	MONT_MAC(v0, v1, v2, u[15], m[21]);
+	MONT_MAC(w0, w1, w2, u[16], m[20]);
+	MONT_MAC(t0, t1, t2, u[17], m[19]);
+	MONT_MAC(v0, v1, v2, u[18], m[18]);
+	MONT_MAC(w0, w1, w2, u[19], m[17]);
+	MONT_MAC(t0, t1, t2, u[20], m[16]);
+	MONT_MAC(v0, v1, v2, u[21], m[15]);
+	MONT_MAC(w0, w1, w2, u[22], m[14]);
+	MONT_MAC(t0, t1, t2, u[23], m[13]);
+	MONT_MAC(v0, v1, v2, u[24], m[12]);
+	MONT_MAC(w0, w1, w2, u[25], m[11]);
+	MONT_MAC(t0, t1, t2, u[26], m[10]);
+	MONT_MAC(v0, v1, v2, u[27], m[9]);
+	MONT_MAC(w0, w1, w2, u[28], m[8]);
+	MONT_MAC(t0, t1, t2, u[29], m[7]);
+	MONT_MAC(v0, v1, v2, u[30], m[6]);
+	MONT_MAC(w0, w1, w2, u[31], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 37 */
+	MONT_MAC(t0, t1, t2, a[6], b[31]);
+	MONT_MUL(v0, v1, v2, a[7], b[30]);
+	MONT_MUL(w0, w1, w2, a[8], b[29]);
+	MONT_MAC(t0, t1, t2, a[9], b[28]);
+	MONT_MAC(v0, v1, v2, a[10], b[27]);
+	MONT_MAC(w0, w1, w2, a[11], b[26]);
+	MONT_MAC(t0, t1, t2, a[12], b[25]);
+	MONT_MAC(v0, v1, v2, a[13], b[24]);
+	MONT_MAC(w0, w1, w2, a[14], b[23]);
+	MONT_MAC(t0, t1, t2, a[15], b[22]);
+	MONT_MAC(v0, v1, v2, a[16], b[21]);
+	MONT_MAC(w0, w1, w2, a[17], b[20]);
+	MONT_MAC(t0, t1, t2, a[18], b[19]);
+	MONT_MAC(v0, v1, v2, a[19], b[18]);
+	MONT_MAC(w0, w1, w2, a[20], b[17]);
+	MONT_MAC(t0, t1, t2, a[21], b[16]);
+	MONT_MAC(v0, v1, v2, a[22], b[15]);
+	MONT_MAC(w0, w1, w2, a[23], b[14]);
+	MONT_MAC(t0, t1, t2, a[24], b[13]);
+	MONT_MAC(v0, v1, v2, a[25], b[12]);
+	MONT_MAC(w0, w1, w2, a[26], b[11]);
+	MONT_MAC(t0, t1, t2, a[27], b[10]);
+	MONT_MAC(v0, v1, v2, a[28], b[9]);
+	MONT_MAC(w0, w1, w2, a[29], b[8]);
+	MONT_MAC(t0, t1, t2, a[30], b[7]);
+	MONT_MAC(v0, v1, v2, a[31], b[6]);
+	MONT_MAC(w0, w1, w2, u[6], m[31]);
+	MONT_MAC(t0, t1, t2, u[7], m[30]);
+	MONT_MAC(v0, v1, v2, u[8], m[29]);
+	MONT_MAC(w0, w1, w2, u[9], m[28]);
+	MONT_MAC(t0, t1, t2, u[10], m[27]);
+	MONT_MAC(v0, v1, v2, u[11], m[26]);
+	MONT_MAC(w0, w1, w2, u[12], m[25]);
+	MONT_MAC(t0, t1, t2, u[13], m[24]);
+	MONT_MAC(v0, v1, v2, u[14], m[23]);
+	MONT_MAC(w0, w1, w2, u[15], m[22]);
+	MONT_MAC(t0, t1, t2, u[16], m[21]);
+	MONT_MAC(v0, v1, v2, u[17], m[20]);
+	MONT_MAC(w0, w1, w2, u[18], m[19]);
+	MONT_MAC(t0, t1, t2, u[19], m[18]);
+	MONT_MAC(v0, v1, v2, u[20], m[17]);
+	MONT_MAC(w0, w1, w2, u[21], m[16]);
+	MONT_MAC(t0, t1, t2, u[22], m[15]);
+	MONT_MAC(v0, v1, v2, u[23], m[14]);
+	MONT_MAC(w0, w1, w2, u[24], m[13]);
+	MONT_MAC(t0, t1, t2, u[25], m[12]);
+	MONT_MAC(v0, v1, v2, u[26], m[11]);
+	MONT_MAC(w0, w1, w2, u[27], m[10]);
+	MONT_MAC(t0, t1, t2, u[28], m[9]);
+	MONT_MAC(v0, v1, v2, u[29], m[8]);
+	MONT_MAC(w0, w1, w2, u[30], m[7]);
+	MONT_MAC(t0, t1, t2, u[31], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 38 */
+	MONT_MAC(t0, t1, t2, a[7], b[31]);
+	MONT_MUL(v0, v1, v2, a[8], b[30]);
+	MONT_MUL(w0, w1, w2, a[9], b[29]);
+	MONT_MAC(t0, t1, t2, a[10], b[28]);
+	MONT_MAC(v0, v1, v2, a[11], b[27]);
+	MONT_MAC(w0, w1, w2, a[12], b[26]);
+	MONT_MAC(t0, t1, t2, a[13], b[25]);
+	MONT_MAC(v0, v1, v2, a[14], b[24]);
+	MONT_MAC(w0, w1, w2, a[15], b[23]);
+	MONT_MAC(t0, t1, t2, a[16], b[22]);
+	MONT_MAC(v0, v1, v2, a[17], b[21]);
+	MONT_MAC(w0, w1, w2, a[18], b[20]);
+	MONT_MAC(t0, t1, t2, a[19], b[19]);
+	MONT_MAC(v0, v1, v2, a[20], b[18]);
+	MONT_MAC(w0, w1, w2, a[21], b[17]);
+	MONT_MAC(t0, t1, t2, a[22], b[16]);
+	MONT_MAC(v0, v1, v2, a[23], b[15]);
+	MONT_MAC(w0, w1, w2, a[24], b[14]);
+	MONT_MAC(t0, t1, t2, a[25], b[13]);
+	MONT_MAC(v0, v1, v2, a[26], b[12]);
+	MONT_MAC(w0, w1, w2, a[27], b[11]);
+	MONT_MAC(t0, t1, t2, a[28], b[10]);
+	MONT_MAC(v0, v1, v2, a[29], b[9]);
+	MONT_MAC(w0, w1, w2, a[30], b[8]);
+	MONT_MAC(t0, t1, t2, a[31], b[7]);
+	MONT_MAC(v0, v1, v2, u[7], m[31]);
+	MONT_MAC(w0, w1, w2, u[8], m[30]);
+	MONT_MAC(t0, t1, t2, u[9], m[29]);
+	MONT_MAC(v0, v1, v2, u[10], m[28]);
+	MONT_MAC(w0, w1, w2, u[11], m[27]);
+	MONT_MAC(t0, t1, t2, u[12], m[26]);
+	MONT_MAC(v0, v1, v2, u[13], m[25]);
+	MONT_MAC(w0, w1, w2, u[14], m[24]);
+	MONT_MAC(t0, t1, t2, u[15], m[23]);
+	MONT_MAC(v0, v1, v2, u[16], m[22]);
+	MONT_MAC(w0, w1, w2, u[17], m[21]);
+	MONT_MAC(t0, t1, t2, u[18], m[20]);
+	MONT_MAC(v0, v1, v2, u[19], m[19]);
+	MONT_MAC(w0, w1, w2, u[20], m[18]);
+	MONT_MAC(t0, t1, t2, u[21], m[17]);
+	MONT_MAC(v0, v1, v2, u[22], m[16]);
+	MONT_MAC(w0, w1, w2, u[23], m[15]);
+	MONT_MAC(t0, t1, t2, u[24], m[14]);
+	MONT_MAC(v0, v1, v2, u[25], m[13]);
+	MONT_MAC(w0, w1, w2, u[26], m[12]);
+	MONT_MAC(t0, t1, t2, u[27], m[11]);
+	MONT_MAC(v0, v1, v2, u[28], m[10]);
+	MONT_MAC(w0, w1, w2, u[29], m[9]);
+	MONT_MAC(t0, t1, t2, u[30], m[8]);
+	MONT_MAC(v0, v1, v2, u[31], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 39 */
+	MONT_MAC(t0, t1, t2, a[8], b[31]);
+	MONT_MUL(v0, v1, v2, a[9], b[30]);
+	MONT_MUL(w0, w1, w2, a[10], b[29]);
+	MONT_MAC(t0, t1, t2, a[11], b[28]);
+	MONT_MAC(v0, v1, v2, a[12], b[27]);
+	MONT_MAC(w0, w1, w2, a[13], b[26]);
+	MONT_MAC(t0, t1, t2, a[14], b[25]);
+	MONT_MAC(v0, v1, v2, a[15], b[24]);
+	MONT_MAC(w0, w1, w2, a[16], b[23]);
+	MONT_MAC(t0, t1, t2, a[17], b[22]);
+	MONT_MAC(v0, v1, v2, a[18], b[21]);
+	MONT_MAC(w0, w1, w2, a[19], b[20]);
+	MONT_MAC(t0, t1, t2, a[20], b[19]);
+	MONT_MAC(v0, v1, v2, a[21], b[18]);
+	MONT_MAC(w0, w1, w2, a[22], b[17]);
+	MONT_MAC(t0, t1, t2, a[23], b[16]);
+	MONT_MAC(v0, v1, v2, a[24], b[15]);
+	MONT_MAC(w0, w1, w2, a[25], b[14]);
+	MONT_MAC(t0, t1, t2, a[26], b[13]);
+	MONT_MAC(v0, v1, v2, a[27], b[12]);
+	MONT_MAC(w0, w1, w2, a[28], b[11]);
+	MONT_MAC(t0, t1, t2, a[29], b[10]);
+	MONT_MAC(v0, v1, v2, a[30], b[9]);
+	MONT_MAC(w0, w1, w2, a[31], b[8]);
+	MONT_MAC(t0, t1, t2, u[8], m[31]);
+	MONT_MAC(v0, v1, v2, u[9], m[30]);
+	MONT_MAC(w0, w1, w2, u[10], m[29]);
+	MONT_MAC(t0, t1, t2, u[11], m[28]);
+	MONT_MAC(v0, v1, v2, u[12], m[27]);
+	MONT_MAC(w0, w1, w2, u[13], m[26]);
+	MONT_MAC(t0, t1, t2, u[14], m[25]);
+	MONT_MAC(v0, v1, v2, u[15], m[24]);
+	MONT_MAC(w0, w1, w2, u[16], m[23]);
+	MONT_MAC(t0, t1, t2, u[17], m[22]);
+	MONT_MAC(v0, v1, v2, u[18], m[21]);
+	MONT_MAC(w0, w1, w2, u[19], m[20]);
+	MONT_MAC(t0, t1, t2, u[20], m[19]);
+	MONT_MAC(v0, v1, v2, u[21], m[18]);
+	MONT_MAC(w0, w1, w2, u[22], m[17]);
+	MONT_MAC(t0, t1, t2, u[23], m[16]);
+	MONT_MAC(v0, v1, v2, u[24], m[15]);
+	MONT_MAC(w0, w1, w2, u[25], m[14]);
+	MONT_MAC(t0, t1, t2, u[26], m[13]);
+	MONT_MAC(v0, v1, v2, u[27], m[12]);
+	MONT_MAC(w0, w1, w2, u[28], m[11]);
+	MONT_MAC(t0, t1, t2, u[29], m[10]);
+	MONT_MAC(v0, v1, v2, u[30], m[9]);
+	MONT_MAC(w0, w1, w2, u[31], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 40 */
+	MONT_MAC(t0, t1, t2, a[9], b[31]);
+	MONT_MUL(v0, v1, v2, a[10], b[30]);
+	MONT_MUL(w0, w1, w2, a[11], b[29]);
+	MONT_MAC(t0, t1, t2, a[12], b[28]);
+	MONT_MAC(v0, v1, v2, a[13], b[27]);
+	MONT_MAC(w0, w1, w2, a[14], b[26]);
+	MONT_MAC(t0, t1, t2, a[15], b[25]);
+	MONT_MAC(v0, v1, v2, a[16], b[24]);
+	MONT_MAC(w0, w1, w2, a[17], b[23]);
+	MONT_MAC(t0, t1, t2, a[18], b[22]);
+	MONT_MAC(v0, v1, v2, a[19], b[21]);
+	MONT_MAC(w0, w1, w2, a[20], b[20]);
+	MONT_MAC(t0, t1, t2, a[21], b[19]);
+	MONT_MAC(v0, v1, v2, a[22], b[18]);
+	MONT_MAC(w0, w1, w2, a[23], b[17]);
+	MONT_MAC(t0, t1, t2, a[24], b[16]);
+	MONT_MAC(v0, v1, v2, a[25], b[15]);
+	MONT_MAC(w0, w1, w2, a[26], b[14]);
+	MONT_MAC(t0, t1, t2, a[27], b[13]);
+	MONT_MAC(v0, v1, v2, a[28], b[12]);
+	MONT_MAC(w0, w1, w2, a[29], b[11]);
+	MONT_MAC(t0, t1, t2, a[30], b[10]);
+	MONT_MAC(v0, v1, v2, a[31], b[9]);
+	MONT_MAC(w0, w1, w2, u[9], m[31]);
+	MONT_MAC(t0, t1, t2, u[10], m[30]);
+	MONT_MAC(v0, v1, v2, u[11], m[29]);
+	MONT_MAC(w0, w1, w2, u[12], m[28]);
+	MONT_MAC(t0, t1, t2, u[13], m[27]);
+	MONT_MAC(v0, v1, v2, u[14], m[26]);
+	MONT_MAC(w0, w1, w2, u[15], m[25]);
+	MONT_MAC(t0, t1, t2, u[16], m[24]);
+	MONT_MAC(v0, v1, v2, u[17], m[23]);
+	MONT_MAC(w0, w1, w2, u[18], m[22]);
+	MONT_MAC(t0, t1, t2, u[19], m[21]);
+	MONT_MAC(v0, v1, v2, u[20], m[20]);
+	MONT_MAC(w0, w1, w2, u[21], m[19]);
+	MONT_MAC(t0, t1, t2, u[22], m[18]);
+	MONT_MAC(v0, v1, v2, u[23], m[17]);
+	MONT_MAC(w0, w1, w2, u[24], m[16]);
+	MONT_MAC(t0, t1, t2, u[25], m[15]);
+	MONT_MAC(v0, v1, v2, u[26], m[14]);
+	MONT_MAC(w0, w1, w2, u[27], m[13]);
+	MONT_MAC(t0, t1, t2, u[28], m[12]);
+	MONT_MAC(v0, v1, v2, u[29], m[11]);
+	MONT_MAC(w0, w1, w2, u[30], m[10]);
+	MONT_MAC(t0, t1, t2, u[31], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 41 */
+	MONT_MAC(t0, t1, t2, a[10], b[31]);
+	MONT_MUL(v0, v1, v2, a[11], b[30]);
+	MONT_MUL(w0, w1, w2, a[12], b[29]);
+	MONT_MAC(t0, t1, t2, a[13], b[28]);
+	MONT_MAC(v0, v1, v2, a[14], b[27]);
+	MONT_MAC(w0, w1, w2, a[15], b[26]);
+	MONT_MAC(t0, t1, t2, a[16], b[25]);
+	MONT_MAC(v0, v1, v2, a[17], b[24]);
+	MONT_MAC(w0, w1, w2, a[18], b[23]);
+	MONT_MAC(t0, t1, t2, a[19], b[22]);
+	MONT_MAC(v0, v1, v2, a[20], b[21]);
+	MONT_MAC(w0, w1, w2, a[21], b[20]);
+	MONT_MAC(t0, t1, t2, a[22], b[19]);
+	MONT_MAC(v0, v1, v2, a[23], b[18]);
+	MONT_MAC(w0, w1, w2, a[24], b[17]);
+	MONT_MAC(t0, t1, t2, a[25], b[16]);
+	MONT_MAC(v0, v1, v2, a[26], b[15]);
+	MONT_MAC(w0, w1, w2, a[27], b[14]);
+	MONT_MAC(t0, t1, t2, a[28], b[13]);
+	MONT_MAC(v0, v1, v2, a[29], b[12]);
+	MONT_MAC(w0, w1, w2, a[30], b[11]);
+	MONT_MAC(t0, t1, t2, a[31], b[10]);
+	MONT_MAC(v0, v1, v2, u[10], m[31]);
+	MONT_MAC(w0, w1, w2, u[11], m[30]);
+	MONT_MAC(t0, t1, t2, u[12], m[29]);
+	MONT_MAC(v0, v1, v2, u[13], m[28]);
+	MONT_MAC(w0, w1, w2, u[14], m[27]);
+	MONT_MAC(t0, t1, t2, u[15], m[26]);
+	MONT_MAC(v0, v1, v2, u[16], m[25]);
+	MONT_MAC(w0, w1, w2, u[17], m[24]);
+	MONT_MAC(t0, t1, t2, u[18], m[23]);
+	MONT_MAC(v0, v1, v2, u[19], m[22]);
+	MONT_MAC(w0, w1, w2, u[20], m[21]);
+	MONT_MAC(t0, t1, t2, u[21], m[20]);
+	MONT_MAC(v0, v1, v2, u[22], m[19]);
+	MONT_MAC(w0, w1, w2, u[23], m[18]);
+	MONT_MAC(t0, t1, t2, u[24], m[17]);
+	MONT_MAC(v0, v1, v2, u[25], m[16]);
+	MONT_MAC(w0, w1, w2, u[26], m[15]);
+	MONT_MAC(t0, t1, t2, u[27], m[14]);
+	MONT_MAC(v0, v1, v2, u[28], m[13]);
+	MONT_MAC(w0, w1, w2, u[29], m[12]);
+	MONT_MAC(t0, t1, t2, u[30], m[11]);
+	MONT_MAC(v0, v1, v2, u[31], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 42 */
+	MONT_MAC(t0, t1, t2, a[11], b[31]);
+	MONT_MUL(v0, v1, v2, a[12], b[30]);
+	MONT_MUL(w0, w1, w2, a[13], b[29]);
+	MONT_MAC(t0, t1, t2, a[14], b[28]);
+	MONT_MAC(v0, v1, v2, a[15], b[27]);
+	MONT_MAC(w0, w1, w2, a[16], b[26]);
+	MONT_MAC(t0, t1, t2, a[17], b[25]);
+	MONT_MAC(v0, v1, v2, a[18], b[24]);
+	MONT_MAC(w0, w1, w2, a[19], b[23]);
+	MONT_MAC(t0, t1, t2, a[20], b[22]);
+	MONT_MAC(v0, v1, v2, a[21], b[21]);
+	MONT_MAC(w0, w1, w2, a[22], b[20]);
+	MONT_MAC(t0, t1, t2, a[23], b[19]);
+	MONT_MAC(v0, v1, v2, a[24], b[18]);
+	MONT_MAC(w0, w1, w2, a[25], b[17]);
+	MONT_MAC(t0, t1, t2, a[26], b[16]);
+	MONT_MAC(v0, v1, v2, a[27], b[15]);
+	MONT_MAC(w0, w1, w2, a[28], b[14]);
+	MONT_MAC(t0, t1, t2, a[29], b[13]);
+	MONT_MAC(v0, v1, v2, a[30], b[12]);
+	MONT_MAC(w0, w1, w2, a[31], b[11]);
+	MONT_MAC(t0, t1, t2, u[11], m[31]);
+	MONT_MAC(v0, v1, v2, u[12], m[30]);
+	MONT_MAC(w0, w1, w2, u[13], m[29]);
+	MONT_MAC(t0, t1, t2, u[14], m[28]);
+	MONT_MAC(v0, v1, v2, u[15], m[27]);
+	MONT_MAC(w0, w1, w2, u[16], m[26]);
+	MONT_MAC(t0, t1, t2, u[17], m[25]);
+	MONT_MAC(v0, v1, v2, u[18], m[24]);
+	MONT_MAC(w0, w1, w2, u[19], m[23]);
+	MONT_MAC(t0, t1, t2, u[20], m[22]);
+	MONT_MAC(v0, v1, v2, u[21], m[21]);
+	MONT_MAC(w0, w1, w2, u[22], m[20]);
+	MONT_MAC(t0, t1, t2, u[23], m[19]);
+	MONT_MAC(v0, v1, v2, u[24], m[18]);
+	MONT_MAC(w0, w1, w2, u[25], m[17]);
+	MONT_MAC(t0, t1, t2, u[26], m[16]);
+	MONT_MAC(v0, v1, v2, u[27], m[15]);
+	MONT_MAC(w0, w1, w2, u[28], m[14]);
+	MONT_MAC(t0, t1, t2, u[29], m[13]);
+	MONT_MAC(v0, v1, v2, u[30], m[12]);
+	MONT_MAC(w0, w1, w2, u[31], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 43 */
+	MONT_MAC(t0, t1, t2, a[12], b[31]);
+	MONT_MUL(v0, v1, v2, a[13], b[30]);
+	MONT_MUL(w0, w1, w2, a[14], b[29]);
+	MONT_MAC(t0, t1, t2, a[15], b[28]);
+	MONT_MAC(v0, v1, v2, a[16], b[27]);
+	MONT_MAC(w0, w1, w2, a[17], b[26]);
+	MONT_MAC(t0, t1, t2, a[18], b[25]);
+	MONT_MAC(v0, v1, v2, a[19], b[24]);
+	MONT_MAC(w0, w1, w2, a[20], b[23]);
+	MONT_MAC(t0, t1, t2, a[21], b[22]);
+	MONT_MAC(v0, v1, v2, a[22], b[21]);
+	MONT_MAC(w0, w1, w2, a[23], b[20]);
+	MONT_MAC(t0, t1, t2, a[24], b[19]);
+	MONT_MAC(v0, v1, v2, a[25], b[18]);
+	MONT_MAC(w0, w1, w2, a[26], b[17]);
+	MONT_MAC(t0, t1, t2, a[27], b[16]);
+	MONT_MAC(v0, v1, v2, a[28], b[15]);
+	MONT_MAC(w0, w1, w2, a[29], b[14]);
+	MONT_MAC(t0, t1, t2, a[30], b[13]);
+	MONT_MAC(v0, v1, v2, a[31], b[12]);
+	MONT_MAC(w0, w1, w2, u[12], m[31]);
+	MONT_MAC(t0, t1, t2, u[13], m[30]);
+	MONT_MAC(v0, v1, v2, u[14], m[29]);
+	MONT_MAC(w0, w1, w2, u[15], m[28]);
+	MONT_MAC(t0, t1, t2, u[16], m[27]);
+	MONT_MAC(v0, v1, v2, u[17], m[26]);
+	MONT_MAC(w0, w1, w2, u[18], m[25]);
+	MONT_MAC(t0, t1, t2, u[19], m[24]);
+	MONT_MAC(v0, v1, v2, u[20], m[23]);
+	MONT_MAC(w0, w1, w2, u[21], m[22]);
+	MONT_MAC(t0, t1, t2, u[22], m[21]);
+	MONT_MAC(v0, v1, v2, u[23], m[20]);
+	MONT_MAC(w0, w1, w2, u[24], m[19]);
+	MONT_MAC(t0, t1, t2, u[25], m[18]);
+	MONT_MAC(v0, v1, v2, u[26], m[17]);
+	MONT_MAC(w0, w1, w2, u[27], m[16]);
+	MONT_MAC(t0, t1, t2, u[28], m[15]);
+	MONT_MAC(v0, v1, v2, u[29], m[14]);
+	MONT_MAC(w0, w1, w2, u[30], m[13]);
+	MONT_MAC(t0, t1, t2, u[31], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 44 */
+	MONT_MAC(t0, t1, t2, a[13], b[31]);
+	MONT_MUL(v0, v1, v2, a[14], b[30]);
+	MONT_MUL(w0, w1, w2, a[15], b[29]);
+	MONT_MAC(t0, t1, t2, a[16], b[28]);
+	MONT_MAC(v0, v1, v2, a[17], b[27]);
+	MONT_MAC(w0, w1, w2, a[18], b[26]);
+	MONT_MAC(t0, t1, t2, a[19], b[25]);
+	MONT_MAC(v0, v1, v2, a[20], b[24]);
+	MONT_MAC(w0, w1, w2, a[21], b[23]);
+	MONT_MAC(t0, t1, t2, a[22], b[22]);
+	MONT_MAC(v0, v1, v2, a[23], b[21]);
+	MONT_MAC(w0, w1, w2, a[24], b[20]);
+	MONT_MAC(t0, t1, t2, a[25], b[19]);
+	MONT_MAC(v0, v1, v2, a[26], b[18]);
+	MONT_MAC(w0, w1, w2, a[27], b[17]);
+	MONT_MAC(t0, t1, t2, a[28], b[16]);
+	MONT_MAC(v0, v1, v2, a[29], b[15]);
+	MONT_MAC(w0, w1, w2, a[30], b[14]);
+	MONT_MAC(t0, t1, t2, a[31], b[13]);
+	MONT_MAC(v0, v1, v2, u[13], m[31]);
+	MONT_MAC(w0, w1, w2, u[14], m[30]);
+	MONT_MAC(t0, t1, t2, u[15], m[29]);
+	MONT_MAC(v0, v1, v2, u[16], m[28]);
+	MONT_MAC(w0, w1, w2, u[17], m[27]);
+	MONT_MAC(t0, t1, t2, u[18], m[26]);
+	MONT_MAC(v0, v1, v2, u[19], m[25]);
+	MONT_MAC(w0, w1, w2, u[20], m[24]);
+	MONT_MAC(t0, t1, t2, u[21], m[23]);
+	MONT_MAC(v0, v1, v2, u[22], m[22]);
+	MONT_MAC(w0, w1, w2, u[23], m[21]);
+	MONT_MAC(t0, t1, t2, u[24], m[20]);
+	MONT_MAC(v0, v1, v2, u[25], m[19]);
+	MONT_MAC(w0, w1, w2, u[26], m[18]);
+	MONT_MAC(t0, t1, t2, u[27], m[17]);
+	MONT_MAC(v0, v1, v2, u[28], m[16]);
+	MONT_MAC(w0, w1, w2, u[29], m[15]);
+	MONT_MAC(t0, t1, t2, u[30], m[14]);
+	MONT_MAC(v0, v1, v2, u[31], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 45 */
+	MONT_MAC(t0, t1, t2, a[14], b[31]);
+	MONT_MUL(v0, v1, v2, a[15], b[30]);
+	MONT_MUL(w0, w1, w2, a[16], b[29]);
+	MONT_MAC(t0, t1, t2, a[17], b[28]);
+	MONT_MAC(v0, v1, v2, a[18], b[27]);
+	MONT_MAC(w0, w1, w2, a[19], b[26]);
+	MONT_MAC(t0, t1, t2, a[20], b[25]);
+	MONT_MAC(v0, v1, v2, a[21], b[24]);
+	MONT_MAC(w0, w1, w2, a[22], b[23]);
+	MONT_MAC(t0, t1, t2, a[23], b[22]);
+	MONT_MAC(v0, v1, v2, a[24], b[21]);
+	MONT_MAC(w0, w1, w2, a[25], b[20]);
+	MONT_MAC(t0, t1, t2, a[26], b[19]);
+	MONT_MAC(v0, v1, v2, a[27], b[18]);
+	MONT_MAC(w0, w1, w2, a[28], b[17]);
+	MONT_MAC(t0, t1, t2, a[29], b[16]);
+	MONT_MAC(v0, v1, v2, a[30], b[15]);
+	MONT_MAC(w0, w1, w2, a[31], b[14]);
+	MONT_MAC(t0, t1, t2, u[14], m[31]);
+	MONT_MAC(v0, v1, v2, u[15], m[30]);
+	MONT_MAC(w0, w1, w2, u[16], m[29]);
+	MONT_MAC(t0, t1, t2, u[17], m[28]);
+	MONT_MAC(v0, v1, v2, u[18], m[27]);
+	MONT_MAC(w0, w1, w2, u[19], m[26]);
+	MONT_MAC(t0, t1, t2, u[20], m[25]);
+	MONT_MAC(v0, v1, v2, u[21], m[24]);
+	MONT_MAC(w0, w1, w2, u[22], m[23]);
+	MONT_MAC(t0, t1, t2, u[23], m[22]);
+	MONT_MAC(v0, v1, v2, u[24], m[21]);
+	MONT_MAC(w0, w1, w2, u[25], m[20]);
+	MONT_MAC(t0, t1, t2, u[26], m[19]);
+	MONT_MAC(v0, v1, v2, u[27], m[18]);
+	MONT_MAC(w0, w1, w2, u[28], m[17]);
+	MONT_MAC(t0, t1, t2, u[29], m[16]);
+	MONT_MAC(v0, v1, v2, u[30], m[15]);
+	MONT_MAC(w0, w1, w2, u[31], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 46 */
+	MONT_MAC(t0, t1, t2, a[15], b[31]);
+	MONT_MUL(v0, v1, v2, a[16], b[30]);
+	MONT_MUL(w0, w1, w2, a[17], b[29]);
+	MONT_MAC(t0, t1, t2, a[18], b[28]);
+	MONT_MAC(v0, v1, v2, a[19], b[27]);
+	MONT_MAC(w0, w1, w2, a[20], b[26]);
+	MONT_MAC(t0, t1, t2, a[21], b[25]);
+	MONT_MAC(v0, v1, v2, a[22], b[24]);
+	MONT_MAC(w0, w1, w2, a[23], b[23]);
+	MONT_MAC(t0, t1, t2, a[24], b[22]);
+	MONT_MAC(v0, v1, v2, a[25], b[21]);
+	MONT_MAC(w0, w1, w2, a[26], b[20]);
+	MONT_MAC(t0, t1, t2, a[27], b[19]);
+	MONT_MAC(v0, v1, v2, a[28], b[18]);
+	MONT_MAC(w0, w1, w2, a[29], b[17]);
+	MONT_MAC(t0, t1, t2, a[30], b[16]);
+	MONT_MAC(v0, v1, v2, a[31], b[15]);
+	MONT_MAC(w0, w1, w2, u[15], m[31]);
+	MONT_MAC(t0, t1, t2, u[16], m[30]);
+	MONT_MAC(v0, v1, v2, u[17], m[29]);
+	MONT_MAC(w0, w1, w2, u[18], m[28]);
+	MONT_MAC(t0, t1, t2, u[19], m[27]);
+	MONT_MAC(v0, v1, v2, u[20], m[26]);
+	MONT_MAC(w0, w1, w2, u[21], m[25]);
+	MONT_MAC(t0, t1, t2, u[22], m[24]);
+	MONT_MAC(v0, v1, v2, u[23], m[23]);
+	MONT_MAC(w0, w1, w2, u[24], m[22]);
+	MONT_MAC(t0, t1, t2, u[25], m[21]);
+	MONT_MAC(v0, v1, v2, u[26], m[20]);
+	MONT_MAC(w0, w1, w2, u[27], m[19]);
+	MONT_MAC(t0, t1, t2, u[28], m[18]);
+	MONT_MAC(v0, v1, v2, u[29], m[17]);
+	MONT_MAC(w0, w1, w2, u[30], m[16]);
+	MONT_MAC(t0, t1, t2, u[31], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[14] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 47 */
+	MONT_MAC(t0, t1, t2, a[16], b[31]);
+	MONT_MUL(v0, v1, v2, a[17], b[30]);
+	MONT_MUL(w0, w1, w2, a[18], b[29]);
+	MONT_MAC(t0, t1, t2, a[19], b[28]);
+	MONT_MAC(v0, v1, v2, a[20], b[27]);
+	MONT_MAC(w0, w1, w2, a[21], b[26]);
+	MONT_MAC(t0, t1, t2, a[22], b[25]);
+	MONT_MAC(v0, v1, v2, a[23], b[24]);
+	MONT_MAC(w0, w1, w2, a[24], b[23]);
+	MONT_MAC(t0, t1, t2, a[25], b[22]);
+	MONT_MAC(v0, v1, v2, a[26], b[21]);
+	MONT_MAC(w0, w1, w2, a[27], b[20]);
+	MONT_MAC(t0, t1, t2, a[28], b[19]);
+	MONT_MAC(v0, v1, v2, a[29], b[18]);
+	MONT_MAC(w0, w1, w2, a[30], b[17]);
+	MONT_MAC(t0, t1, t2, a[31], b[16]);
+	MONT_MAC(v0, v1, v2, u[16], m[31]);
+	MONT_MAC(w0, w1, w2, u[17], m[30]);
+	MONT_MAC(t0, t1, t2, u[18], m[29]);
+	MONT_MAC(v0, v1, v2, u[19], m[28]);
+	MONT_MAC(w0, w1, w2, u[20], m[27]);
+	MONT_MAC(t0, t1, t2, u[21], m[26]);
+	MONT_MAC(v0, v1, v2, u[22], m[25]);
+	MONT_MAC(w0, w1, w2, u[23], m[24]);
+	MONT_MAC(t0, t1, t2, u[24], m[23]);
+	MONT_MAC(v0, v1, v2, u[25], m[22]);
+	MONT_MAC(w0, w1, w2, u[26], m[21]);
+	MONT_MAC(t0, t1, t2, u[27], m[20]);
+	MONT_MAC(v0, v1, v2, u[28], m[19]);
+	MONT_MAC(w0, w1, w2, u[29], m[18]);
+	MONT_MAC(t0, t1, t2, u[30], m[17]);
+	MONT_MAC(v0, v1, v2, u[31], m[16]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[15] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 48 */
+	MONT_MAC(t0, t1, t2, a[17], b[31]);
+	MONT_MUL(v0, v1, v2, a[18], b[30]);
+	MONT_MUL(w0, w1, w2, a[19], b[29]);
+	MONT_MAC(t0, t1, t2, a[20], b[28]);
+	MONT_MAC(v0, v1, v2, a[21], b[27]);
+	MONT_MAC(w0, w1, w2, a[22], b[26]);
+	MONT_MAC(t0, t1, t2, a[23], b[25]);
+	MONT_MAC(v0, v1, v2, a[24], b[24]);
+	MONT_MAC(w0, w1, w2, a[25], b[23]);
+	MONT_MAC(t0, t1, t2, a[26], b[22]);
+	MONT_MAC(v0, v1, v2, a[27], b[21]);
+	MONT_MAC(w0, w1, w2, a[28], b[20]);
+	MONT_MAC(t0, t1, t2, a[29], b[19]);
+	MONT_MAC(v0, v1, v2, a[30], b[18]);
+	MONT_MAC(w0, w1, w2, a[31], b[17]);
+	MONT_MAC(t0, t1, t2, u[17], m[31]);
+	MONT_MAC(v0, v1, v2, u[18], m[30]);
+	MONT_MAC(w0, w1, w2, u[19], m[29]);
+	MONT_MAC(t0, t1, t2, u[20], m[28]);
+	MONT_MAC(v0, v1, v2, u[21], m[27]);
+	MONT_MAC(w0, w1, w2, u[22], m[26]);
+	MONT_MAC(t0, t1, t2, u[23], m[25]);
+	MONT_MAC(v0, v1, v2, u[24], m[24]);
+	MONT_MAC(w0, w1, w2, u[25], m[23]);
+	MONT_MAC(t0, t1, t2, u[26], m[22]);
+	MONT_MAC(v0, v1, v2, u[27], m[21]);
+	MONT_MAC(w0, w1, w2, u[28], m[20]);
+	MONT_MAC(t0, t1, t2, u[29], m[19]);
+	MONT_MAC(v0, v1, v2, u[30], m[18]);
+	MONT_MAC(w0, w1, w2, u[31], m[17]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[16] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 49 */
+	MONT_MAC(t0, t1, t2, a[18], b[31]);
+	MONT_MUL(v0, v1, v2, a[19], b[30]);
+	MONT_MUL(w0, w1, w2, a[20], b[29]);
+	MONT_MAC(t0, t1, t2, a[21], b[28]);
+	MONT_MAC(v0, v1, v2, a[22], b[27]);
+	MONT_MAC(w0, w1, w2, a[23], b[26]);
+	MONT_MAC(t0, t1, t2, a[24], b[25]);
+	MONT_MAC(v0, v1, v2, a[25], b[24]);
+	MONT_MAC(w0, w1, w2, a[26], b[23]);
+	MONT_MAC(t0, t1, t2, a[27], b[22]);
+	MONT_MAC(v0, v1, v2, a[28], b[21]);
+	MONT_MAC(w0, w1, w2, a[29], b[20]);
+	MONT_MAC(t0, t1, t2, a[30], b[19]);
+	MONT_MAC(v0, v1, v2, a[31], b[18]);
+	MONT_MAC(w0, w1, w2, u[18], m[31]);
+	MONT_MAC(t0, t1, t2, u[19], m[30]);
+	MONT_MAC(v0, v1, v2, u[20], m[29]);
+	MONT_MAC(w0, w1, w2, u[21], m[28]);
+	MONT_MAC(t0, t1, t2, u[22], m[27]);
+	MONT_MAC(v0, v1, v2, u[23], m[26]);
+	MONT_MAC(w0, w1, w2, u[24], m[25]);
+	MONT_MAC(t0, t1, t2, u[25], m[24]);
+	MONT_MAC(v0, v1, v2, u[26], m[23]);
+	MONT_MAC(w0, w1, w2, u[27], m[22]);
+	MONT_MAC(t0, t1, t2, u[28], m[21]);
+	MONT_MAC(v0, v1, v2, u[29], m[20]);
+	MONT_MAC(w0, w1, w2, u[30], m[19]);
+	MONT_MAC(t0, t1, t2, u[31], m[18]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[17] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 50 */
+	MONT_MAC(t0, t1, t2, a[19], b[31]);
+	MONT_MUL(v0, v1, v2, a[20], b[30]);
+	MONT_MUL(w0, w1, w2, a[21], b[29]);
+	MONT_MAC(t0, t1, t2, a[22], b[28]);
+	MONT_MAC(v0, v1, v2, a[23], b[27]);
+	MONT_MAC(w0, w1, w2, a[24], b[26]);
+	MONT_MAC(t0, t1, t2, a[25], b[25]);
+	MONT_MAC(v0, v1, v2, a[26], b[24]);
+	MONT_MAC(w0, w1, w2, a[27], b[23]);
+	MONT_MAC(t0, t1, t2, a[28], b[22]);
+	MONT_MAC(v0, v1, v2, a[29], b[21]);
+	MONT_MAC(w0, w1, w2, a[30], b[20]);
+	MONT_MAC(t0, t1, t2, a[31], b[19]);
+	MONT_MAC(v0, v1, v2, u[19], m[31]);
+	MONT_MAC(w0, w1, w2, u[20], m[30]);
+	MONT_MAC(t0, t1, t2, u[21], m[29]);
+	MONT_MAC(v0, v1, v2, u[22], m[28]);
+	MONT_MAC(w0, w1, w2, u[23], m[27]);
+	MONT_MAC(t0, t1, t2, u[24], m[26]);
+	MONT_MAC(v0, v1, v2, u[25], m[25]);
+	MONT_MAC(w0, w1, w2, u[26], m[24]);
+	MONT_MAC(t0, t1, t2, u[27], m[23]);
+	MONT_MAC(v0, v1, v2, u[28], m[22]);
+	MONT_MAC(w0, w1, w2, u[29], m[21]);
+	MONT_MAC(t0, t1, t2, u[30], m[20]);
+	MONT_MAC(v0, v1, v2, u[31], m[19]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[18] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 51 */
+	MONT_MAC(t0, t1, t2, a[20], b[31]);
+	MONT_MUL(v0, v1, v2, a[21], b[30]);
+	MONT_MUL(w0, w1, w2, a[22], b[29]);
+	MONT_MAC(t0, t1, t2, a[23], b[28]);
+	MONT_MAC(v0, v1, v2, a[24], b[27]);
+	MONT_MAC(w0, w1, w2, a[25], b[26]);
+	MONT_MAC(t0, t1, t2, a[26], b[25]);
+	MONT_MAC(v0, v1, v2, a[27], b[24]);
+	MONT_MAC(w0, w1, w2, a[28], b[23]);
+	MONT_MAC(t0, t1, t2, a[29], b[22]);
+	MONT_MAC(v0, v1, v2, a[30], b[21]);
+	MONT_MAC(w0, w1, w2, a[31], b[20]);
+	MONT_MAC(t0, t1, t2, u[20], m[31]);
+	MONT_MAC(v0, v1, v2, u[21], m[30]);
+	MONT_MAC(w0, w1, w2, u[22], m[29]);
+	MONT_MAC(t0, t1, t2, u[23], m[28]);
+	MONT_MAC(v0, v1, v2, u[24], m[27]);
+	MONT_MAC(w0, w1, w2, u[25], m[26]);
+	MONT_MAC(t0, t1, t2, u[26], m[25]);
+	MONT_MAC(v0, v1, v2, u[27], m[24]);
+	MONT_MAC(w0, w1, w2, u[28], m[23]);
+	MONT_MAC(t0, t1, t2, u[29], m[22]);
+	MONT_MAC(v0, v1, v2, u[30], m[21]);
+	MONT_MAC(w0, w1, w2, u[31], m[20]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[19] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 52 */
+	MONT_MAC(t0, t1, t2, a[21], b[31]);
+	MONT_MUL(v0, v1, v2, a[22], b[30]);
+	MONT_MUL(w0, w1, w2, a[23], b[29]);
+	MONT_MAC(t0, t1, t2, a[24], b[28]);
+	MONT_MAC(v0, v1, v2, a[25], b[27]);
+	MONT_MAC(w0, w1, w2, a[26], b[26]);
+	MONT_MAC(t0, t1, t2, a[27], b[25]);
+	MONT_MAC(v0, v1, v2, a[28], b[24]);
+	MONT_MAC(w0, w1, w2, a[29], b[23]);
+	MONT_MAC(t0, t1, t2, a[30], b[22]);
+	MONT_MAC(v0, v1, v2, a[31], b[21]);
+	MONT_MAC(w0, w1, w2, u[21], m[31]);
+	MONT_MAC(t0, t1, t2, u[22], m[30]);
+	MONT_MAC(v0, v1, v2, u[23], m[29]);
+	MONT_MAC(w0, w1, w2, u[24], m[28]);
+	MONT_MAC(t0, t1, t2, u[25], m[27]);
+	MONT_MAC(v0, v1, v2, u[26], m[26]);
+	MONT_MAC(w0, w1, w2, u[27], m[25]);
+	MONT_MAC(t0, t1, t2, u[28], m[24]);
+	MONT_MAC(v0, v1, v2, u[29], m[23]);
+	MONT_MAC(w0, w1, w2, u[30], m[22]);
+	MONT_MAC(t0, t1, t2, u[31], m[21]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[20] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 53 */
+	MONT_MAC(t0, t1, t2, a[22], b[31]);
+	MONT_MUL(v0, v1, v2, a[23], b[30]);
+	MONT_MUL(w0, w1, w2, a[24], b[29]);
+	MONT_MAC(t0, t1, t2, a[25], b[28]);
+	MONT_MAC(v0, v1, v2, a[26], b[27]);
+	MONT_MAC(w0, w1, w2, a[27], b[26]);
+	MONT_MAC(t0, t1, t2, a[28], b[25]);
+	MONT_MAC(v0, v1, v2, a[29], b[24]);
+	MONT_MAC(w0, w1, w2, a[30], b[23]);
+	MONT_MAC(t0, t1, t2, a[31], b[22]);
+	MONT_MAC(v0, v1, v2, u[22], m[31]);
+	MONT_MAC(w0, w1, w2, u[23], m[30]);
+	MONT_MAC(t0, t1, t2, u[24], m[29]);
+	MONT_MAC(v0, v1, v2, u[25], m[28]);
+	MONT_MAC(w0, w1, w2, u[26], m[27]);
+	MONT_MAC(t0, t1, t2, u[27], m[26]);
+	MONT_MAC(v0, v1, v2, u[28], m[25]);
+	MONT_MAC(w0, w1, w2, u[29], m[24]);
+	MONT_MAC(t0, t1, t2, u[30], m[23]);
+	MONT_MAC(v0, v1, v2, u[31], m[22]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[21] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 54 */
+	MONT_MAC(t0, t1, t2, a[23], b[31]);
+	MONT_MUL(v0, v1, v2, a[24], b[30]);
+	MONT_MUL(w0, w1, w2, a[25], b[29]);
+	MONT_MAC(t0, t1, t2, a[26], b[28]);
+	MONT_MAC(v0, v1, v2, a[27], b[27]);
+	MONT_MAC(w0, w1, w2, a[28], b[26]);
+	MONT_MAC(t0, t1, t2, a[29], b[25]);
+	MONT_MAC(v0, v1, v2, a[30], b[24]);
+	MONT_MAC(w0, w1, w2, a[31], b[23]);
+	MONT_MAC(t0, t1, t2, u[23], m[31]);
+	MONT_MAC(v0, v1, v2, u[24], m[30]);
+	MONT_MAC(w0, w1, w2, u[25], m[29]);
+	MONT_MAC(t0, t1, t2, u[26], m[28]);
+	MONT_MAC(v0, v1, v2, u[27], m[27]);
+	MONT_MAC(w0, w1, w2, u[28], m[26]);
+	MONT_MAC(t0, t1, t2, u[29], m[25]);
+	MONT_MAC(v0, v1, v2, u[30], m[24]);
+	MONT_MAC(w0, w1, w2, u[31], m[23]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[22] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 55 */
+	MONT_MAC(t0, t1, t2, a[24], b[31]);
+	MONT_MUL(v0, v1, v2, a[25], b[30]);
+	MONT_MUL(w0, w1, w2, a[26], b[29]);
+	MONT_MAC(t0, t1, t2, a[27], b[28]);
+	MONT_MAC(v0, v1, v2, a[28], b[27]);
+	MONT_MAC(w0, w1, w2, a[29], b[26]);
+	MONT_MAC(t0, t1, t2, a[30], b[25]);
+	MONT_MAC(v0, v1, v2, a[31], b[24]);
+	MONT_MAC(w0, w1, w2, u[24], m[31]);
+	MONT_MAC(t0, t1, t2, u[25], m[30]);
+	MONT_MAC(v0, v1, v2, u[26], m[29]);
+	MONT_MAC(w0, w1, w2, u[27], m[28]);
+	MONT_MAC(t0, t1, t2, u[28], m[27]);
+	MONT_MAC(v0, v1, v2, u[29], m[26]);
+	MONT_MAC(w0, w1, w2, u[30], m[25]);
+	MONT_MAC(t0, t1, t2, u[31], m[24]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[23] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 56 */
+	MONT_MAC(t0, t1, t2, a[25], b[31]);
+	MONT_MUL(v0, v1, v2, a[26], b[30]);
+	MONT_MUL(w0, w1, w2, a[27], b[29]);
+	MONT_MAC(t0, t1, t2, a[28], b[28]);
+	MONT_MAC(v0, v1, v2, a[29], b[27]);
+	MONT_MAC(w0, w1, w2, a[30], b[26]);
+	MONT_MAC(t0, t1, t2, a[31], b[25]);
+	MONT_MAC(v0, v1, v2, u[25], m[31]);
+	MONT_MAC(w0, w1, w2, u[26], m[30]);
+	MONT_MAC(t0, t1, t2, u[27], m[29]);
+	MONT_MAC(v0, v1, v2, u[28], m[28]);
+	MONT_MAC(w0, w1, w2, u[29], m[27]);
+	MONT_MAC(t0, t1, t2, u[30], m[26]);
+	MONT_MAC(v0, v1, v2, u[31], m[25]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[24] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 57 */
+	MONT_MAC(t0, t1, t2, a[26], b[31]);
+	MONT_MUL(v0, v1, v2, a[27], b[30]);
+	MONT_MUL(w0, w1, w2, a[28], b[29]);
+	MONT_MAC(t0, t1, t2, a[29], b[28]);
+	MONT_MAC(v0, v1, v2, a[30], b[27]);
+	MONT_MAC(w0, w1, w2, a[31], b[26]);
+	MONT_MAC(t0, t1, t2, u[26], m[31]);
+	MONT_MAC(v0, v1, v2, u[27], m[30]);
+	MONT_MAC(w0, w1, w2, u[28], m[29]);
+	MONT_MAC(t0, t1, t2, u[29], m[28]);
+	MONT_MAC(v0, v1, v2, u[30], m[27]);
+	MONT_MAC(w0, w1, w2, u[31], m[26]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[25] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 58 */
+	MONT_MAC(t0, t1, t2, a[27], b[31]);
+	MONT_MUL(v0, v1, v2, a[28], b[30]);
+	MONT_MUL(w0, w1, w2, a[29], b[29]);
+	MONT_MAC(t0, t1, t2, a[30], b[28]);
+	MONT_MAC(v0, v1, v2, a[31], b[27]);
+	MONT_MAC(w0, w1, w2, u[27], m[31]);
+	MONT_MAC(t0, t1, t2, u[28], m[30]);
+	MONT_MAC(v0, v1, v2, u[29], m[29]);
+	MONT_MAC(w0, w1, w2, u[30], m[28]);
+	MONT_MAC(t0, t1, t2, u[31], m[27]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[26] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 59 */
+	MONT_MAC(t0, t1, t2, a[28], b[31]);
+	MONT_MUL(v0, v1, v2, a[29], b[30]);
+	MONT_MUL(w0, w1, w2, a[30], b[29]);
+	MONT_MAC(t0, t1, t2, a[31], b[28]);
+	MONT_MAC(v0, v1, v2, u[28], m[31]);
+	MONT_MAC(w0, w1, w2, u[29], m[30]);
+	MONT_MAC(t0, t1, t2, u[30], m[29]);
+	MONT_MAC(v0, v1, v2, u[31], m[28]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[27] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 60 */
+	MONT_MAC(t0, t1, t2, a[29], b[31]);
+	MONT_MUL(v0, v1, v2, a[30], b[30]);
+	MONT_MUL(w0, w1, w2, a[31], b[29]);
+	MONT_MAC(t0, t1, t2, u[29], m[31]);
+	MONT_MAC(v0, v1, v2, u[30], m[30]);
+	MONT_MAC(w0, w1, w2, u[31], m[29]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[28] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 61 */
+	MONT_MAC(t0, t1, t2, a[30], b[31]);
+	MONT_MUL(v0, v1, v2, a[31], b[30]);
+	MONT_MUL(w0, w1, w2, u[30], m[31]);
+	MONT_MAC(t0, t1, t2, u[31], m[30]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	z[29] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 62 */
+	MONT_MAC(t0, t1, t2, a[31], b[31]);
+	MONT_MUL(v0, v1, v2, u[31], m[31]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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);
+}
+
+/* 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, v0, v1, v2, w0, w1, w2, borrow, take;
+	limb_t s0, s1, s2, c0, c1, c2;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], a[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MUL(s0, s1, s2, a[0], a[1]);
+	MONT_MAC(t0, t1, t2, u[0], m[1]);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MUL(s0, s1, s2, a[0], a[2]);
+	MONT_MAC(t0, t1, t2, a[1], a[1]);
+	MONT_MUL(v0, v1, v2, u[0], m[2]);
+	MONT_MUL(w0, w1, w2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MUL(s0, s1, s2, a[0], a[3]);
+	MONT_MUL(c0, c1, c2, a[1], a[2]);
+	MONT_MAC(t0, t1, t2, u[0], m[3]);
+	MONT_MUL(v0, v1, v2, u[1], m[2]);
+	MONT_MUL(w0, w1, w2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MUL(s0, s1, s2, a[0], a[4]);
+	MONT_MUL(c0, c1, c2, a[1], a[3]);
+	MONT_MAC(t0, t1, t2, a[2], a[2]);
+	MONT_MUL(v0, v1, v2, u[0], m[4]);
+	MONT_MUL(w0, w1, w2, u[1], m[3]);
+	MONT_MAC(t0, t1, t2, u[2], m[2]);
+	MONT_MAC(v0, v1, v2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MUL(s0, s1, s2, a[0], a[5]);
+	MONT_MUL(c0, c1, c2, a[1], a[4]);
+	MONT_MAC(s0, s1, s2, a[2], a[3]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MUL(v0, v1, v2, u[1], m[4]);
+	MONT_MUL(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MUL(s0, s1, s2, a[0], a[6]);
+	MONT_MUL(c0, c1, c2, a[1], a[5]);
+	MONT_MAC(s0, s1, s2, a[2], a[4]);
+	MONT_MAC(t0, t1, t2, a[3], a[3]);
+	MONT_MUL(v0, v1, v2, u[0], m[6]);
+	MONT_MUL(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MUL(s0, s1, s2, a[0], a[7]);
+	MONT_MUL(c0, c1, c2, a[1], a[6]);
+	MONT_MAC(s0, s1, s2, a[2], a[5]);
+	MONT_MAC(c0, c1, c2, a[3], a[4]);
+	MONT_MAC(t0, t1, t2, u[0], m[7]);
+	MONT_MUL(v0, v1, v2, u[1], m[6]);
+	MONT_MUL(w0, w1, w2, u[2], m[5]);
+	MONT_MAC(t0, t1, t2, u[3], m[4]);
+	MONT_MAC(v0, v1, v2, u[4], m[3]);
+	MONT_MAC(w0, w1, w2, u[5], m[2]);
+	MONT_MAC(t0, t1, t2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MUL(s0, s1, s2, a[0], a[8]);
+	MONT_MUL(c0, c1, c2, a[1], a[7]);
+	MONT_MAC(s0, s1, s2, a[2], a[6]);
+	MONT_MAC(c0, c1, c2, a[3], a[5]);
+	MONT_MAC(t0, t1, t2, a[4], a[4]);
+	MONT_MUL(v0, v1, v2, u[0], m[8]);
+	MONT_MUL(w0, w1, w2, u[1], m[7]);
+	MONT_MAC(t0, t1, t2, u[2], m[6]);
+	MONT_MAC(v0, v1, v2, u[3], m[5]);
+	MONT_MAC(w0, w1, w2, u[4], m[4]);
+	MONT_MAC(t0, t1, t2, u[5], m[3]);
+	MONT_MAC(v0, v1, v2, u[6], m[2]);
+	MONT_MAC(w0, w1, w2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MUL(s0, s1, s2, a[0], a[9]);
+	MONT_MUL(c0, c1, c2, a[1], a[8]);
+	MONT_MAC(s0, s1, s2, a[2], a[7]);
+	MONT_MAC(c0, c1, c2, a[3], a[6]);
+	MONT_MAC(s0, s1, s2, a[4], a[5]);
+	MONT_MAC(t0, t1, t2, u[0], m[9]);
+	MONT_MUL(v0, v1, v2, u[1], m[8]);
+	MONT_MUL(w0, w1, w2, u[2], m[7]);
+	MONT_MAC(t0, t1, t2, u[3], m[6]);
+	MONT_MAC(v0, v1, v2, u[4], m[5]);
+	MONT_MAC(w0, w1, w2, u[5], m[4]);
+	MONT_MAC(t0, t1, t2, u[6], m[3]);
+	MONT_MAC(v0, v1, v2, u[7], m[2]);
+	MONT_MAC(w0, w1, w2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MUL(s0, s1, s2, a[0], a[10]);
+	MONT_MUL(c0, c1, c2, a[1], a[9]);
+	MONT_MAC(s0, s1, s2, a[2], a[8]);
+	MONT_MAC(c0, c1, c2, a[3], a[7]);
+	MONT_MAC(s0, s1, s2, a[4], a[6]);
+	MONT_MAC(t0, t1, t2, a[5], a[5]);
+	MONT_MUL(v0, v1, v2, u[0], m[10]);
+	MONT_MUL(w0, w1, w2, u[1], m[9]);
+	MONT_MAC(t0, t1, t2, u[2], m[8]);
+	MONT_MAC(v0, v1, v2, u[3], m[7]);
+	MONT_MAC(w0, w1, w2, u[4], m[6]);
+	MONT_MAC(t0, t1, t2, u[5], m[5]);
+	MONT_MAC(v0, v1, v2, u[6], m[4]);
+	MONT_MAC(w0, w1, w2, u[7], m[3]);
+	MONT_MAC(t0, t1, t2, u[8], m[2]);
+	MONT_MAC(v0, v1, v2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MUL(s0, s1, s2, a[0], a[11]);
+	MONT_MUL(c0, c1, c2, a[1], a[10]);
+	MONT_MAC(s0, s1, s2, a[2], a[9]);
+	MONT_MAC(c0, c1, c2, a[3], a[8]);
+	MONT_MAC(s0, s1, s2, a[4], a[7]);
+	MONT_MAC(c0, c1, c2, a[5], a[6]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MUL(v0, v1, v2, u[1], m[10]);
+	MONT_MUL(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MUL(s0, s1, s2, a[0], a[12]);
+	MONT_MUL(c0, c1, c2, a[1], a[11]);
+	MONT_MAC(s0, s1, s2, a[2], a[10]);
+	MONT_MAC(c0, c1, c2, a[3], a[9]);
+	MONT_MAC(s0, s1, s2, a[4], a[8]);
+	MONT_MAC(c0, c1, c2, a[5], a[7]);
+	MONT_MAC(t0, t1, t2, a[6], a[6]);
+	MONT_MUL(v0, v1, v2, u[0], m[12]);
+	MONT_MUL(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MUL(s0, s1, s2, a[0], a[13]);
+	MONT_MUL(c0, c1, c2, a[1], a[12]);
+	MONT_MAC(s0, s1, s2, a[2], a[11]);
+	MONT_MAC(c0, c1, c2, a[3], a[10]);
+	MONT_MAC(s0, s1, s2, a[4], a[9]);
+	MONT_MAC(c0, c1, c2, a[5], a[8]);
+	MONT_MAC(s0, s1, s2, a[6], a[7]);
+	MONT_MAC(t0, t1, t2, u[0], m[13]);
+	MONT_MUL(v0, v1, v2, u[1], m[12]);
+	MONT_MUL(w0, w1, w2, u[2], m[11]);
+	MONT_MAC(t0, t1, t2, u[3], m[10]);
+	MONT_MAC(v0, v1, v2, u[4], m[9]);
+	MONT_MAC(w0, w1, w2, u[5], m[8]);
+	MONT_MAC(t0, t1, t2, u[6], m[7]);
+	MONT_MAC(v0, v1, v2, u[7], m[6]);
+	MONT_MAC(w0, w1, w2, u[8], m[5]);
+	MONT_MAC(t0, t1, t2, u[9], m[4]);
+	MONT_MAC(v0, v1, v2, u[10], m[3]);
+	MONT_MAC(w0, w1, w2, u[11], m[2]);
+	MONT_MAC(t0, t1, t2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MUL(s0, s1, s2, a[0], a[14]);
+	MONT_MUL(c0, c1, c2, a[1], a[13]);
+	MONT_MAC(s0, s1, s2, a[2], a[12]);
+	MONT_MAC(c0, c1, c2, a[3], a[11]);
+	MONT_MAC(s0, s1, s2, a[4], a[10]);
+	MONT_MAC(c0, c1, c2, a[5], a[9]);
+	MONT_MAC(s0, s1, s2, a[6], a[8]);
+	MONT_MAC(t0, t1, t2, a[7], a[7]);
+	MONT_MUL(v0, v1, v2, u[0], m[14]);
+	MONT_MUL(w0, w1, w2, u[1], m[13]);
+	MONT_MAC(t0, t1, t2, u[2], m[12]);
+	MONT_MAC(v0, v1, v2, u[3], m[11]);
+	MONT_MAC(w0, w1, w2, u[4], m[10]);
+	MONT_MAC(t0, t1, t2, u[5], m[9]);
+	MONT_MAC(v0, v1, v2, u[6], m[8]);
+	MONT_MAC(w0, w1, w2, u[7], m[7]);
+	MONT_MAC(t0, t1, t2, u[8], m[6]);
+	MONT_MAC(v0, v1, v2, u[9], m[5]);
+	MONT_MAC(w0, w1, w2, u[10], m[4]);
+	MONT_MAC(t0, t1, t2, u[11], m[3]);
+	MONT_MAC(v0, v1, v2, u[12], m[2]);
+	MONT_MAC(w0, w1, w2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MUL(s0, s1, s2, a[0], a[15]);
+	MONT_MUL(c0, c1, c2, a[1], a[14]);
+	MONT_MAC(s0, s1, s2, a[2], a[13]);
+	MONT_MAC(c0, c1, c2, a[3], a[12]);
+	MONT_MAC(s0, s1, s2, a[4], a[11]);
+	MONT_MAC(c0, c1, c2, a[5], a[10]);
+	MONT_MAC(s0, s1, s2, a[6], a[9]);
+	MONT_MAC(c0, c1, c2, a[7], a[8]);
+	MONT_MAC(t0, t1, t2, u[0], m[15]);
+	MONT_MUL(v0, v1, v2, u[1], m[14]);
+	MONT_MUL(w0, w1, w2, u[2], m[13]);
+	MONT_MAC(t0, t1, t2, u[3], m[12]);
+	MONT_MAC(v0, v1, v2, u[4], m[11]);
+	MONT_MAC(w0, w1, w2, u[5], m[10]);
+	MONT_MAC(t0, t1, t2, u[6], m[9]);
+	MONT_MAC(v0, v1, v2, u[7], m[8]);
+	MONT_MAC(w0, w1, w2, u[8], m[7]);
+	MONT_MAC(t0, t1, t2, u[9], m[6]);
+	MONT_MAC(v0, v1, v2, u[10], m[5]);
+	MONT_MAC(w0, w1, w2, u[11], m[4]);
+	MONT_MAC(t0, t1, t2, u[12], m[3]);
+	MONT_MAC(v0, v1, v2, u[13], m[2]);
+	MONT_MAC(w0, w1, w2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MUL(s0, s1, s2, a[0], a[16]);
+	MONT_MUL(c0, c1, c2, a[1], a[15]);
+	MONT_MAC(s0, s1, s2, a[2], a[14]);
+	MONT_MAC(c0, c1, c2, a[3], a[13]);
+	MONT_MAC(s0, s1, s2, a[4], a[12]);
+	MONT_MAC(c0, c1, c2, a[5], a[11]);
+	MONT_MAC(s0, s1, s2, a[6], a[10]);
+	MONT_MAC(c0, c1, c2, a[7], a[9]);
+	MONT_MAC(t0, t1, t2, a[8], a[8]);
+	MONT_MUL(v0, v1, v2, u[0], m[16]);
+	MONT_MUL(w0, w1, w2, u[1], m[15]);
+	MONT_MAC(t0, t1, t2, u[2], m[14]);
+	MONT_MAC(v0, v1, v2, u[3], m[13]);
+	MONT_MAC(w0, w1, w2, u[4], m[12]);
+	MONT_MAC(t0, t1, t2, u[5], m[11]);
+	MONT_MAC(v0, v1, v2, u[6], m[10]);
+	MONT_MAC(w0, w1, w2, u[7], m[9]);
+	MONT_MAC(t0, t1, t2, u[8], m[8]);
+	MONT_MAC(v0, v1, v2, u[9], m[7]);
+	MONT_MAC(w0, w1, w2, u[10], m[6]);
+	MONT_MAC(t0, t1, t2, u[11], m[5]);
+	MONT_MAC(v0, v1, v2, u[12], m[4]);
+	MONT_MAC(w0, w1, w2, u[13], m[3]);
+	MONT_MAC(t0, t1, t2, u[14], m[2]);
+	MONT_MAC(v0, v1, v2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[16] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[16], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MUL(s0, s1, s2, a[0], a[17]);
+	MONT_MUL(c0, c1, c2, a[1], a[16]);
+	MONT_MAC(s0, s1, s2, a[2], a[15]);
+	MONT_MAC(c0, c1, c2, a[3], a[14]);
+	MONT_MAC(s0, s1, s2, a[4], a[13]);
+	MONT_MAC(c0, c1, c2, a[5], a[12]);
+	MONT_MAC(s0, s1, s2, a[6], a[11]);
+	MONT_MAC(c0, c1, c2, a[7], a[10]);
+	MONT_MAC(s0, s1, s2, a[8], a[9]);
+	MONT_MAC(t0, t1, t2, u[0], m[17]);
+	MONT_MUL(v0, v1, v2, u[1], m[16]);
+	MONT_MUL(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_MAC(v0, v1, v2, u[16], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[17] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[17], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MUL(s0, s1, s2, a[0], a[18]);
+	MONT_MUL(c0, c1, c2, a[1], a[17]);
+	MONT_MAC(s0, s1, s2, a[2], a[16]);
+	MONT_MAC(c0, c1, c2, a[3], a[15]);
+	MONT_MAC(s0, s1, s2, a[4], a[14]);
+	MONT_MAC(c0, c1, c2, a[5], a[13]);
+	MONT_MAC(s0, s1, s2, a[6], a[12]);
+	MONT_MAC(c0, c1, c2, a[7], a[11]);
+	MONT_MAC(s0, s1, s2, a[8], a[10]);
+	MONT_MAC(t0, t1, t2, a[9], a[9]);
+	MONT_MUL(v0, v1, v2, u[0], m[18]);
+	MONT_MUL(w0, w1, w2, u[1], m[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[16]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_MAC(w0, w1, w2, u[16], m[2]);
+	MONT_MAC(t0, t1, t2, u[17], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[18] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[18], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MUL(s0, s1, s2, a[0], a[19]);
+	MONT_MUL(c0, c1, c2, a[1], a[18]);
+	MONT_MAC(s0, s1, s2, a[2], a[17]);
+	MONT_MAC(c0, c1, c2, a[3], a[16]);
+	MONT_MAC(s0, s1, s2, a[4], a[15]);
+	MONT_MAC(c0, c1, c2, a[5], a[14]);
+	MONT_MAC(s0, s1, s2, a[6], a[13]);
+	MONT_MAC(c0, c1, c2, a[7], a[12]);
+	MONT_MAC(s0, s1, s2, a[8], a[11]);
+	MONT_MAC(c0, c1, c2, a[9], a[10]);
+	MONT_MAC(t0, t1, t2, u[0], m[19]);
+	MONT_MUL(v0, v1, v2, u[1], m[18]);
+	MONT_MUL(w0, w1, w2, u[2], m[17]);
+	MONT_MAC(t0, t1, t2, u[3], m[16]);
+	MONT_MAC(v0, v1, v2, u[4], m[15]);
+	MONT_MAC(w0, w1, w2, u[5], m[14]);
+	MONT_MAC(t0, t1, t2, u[6], m[13]);
+	MONT_MAC(v0, v1, v2, u[7], m[12]);
+	MONT_MAC(w0, w1, w2, u[8], m[11]);
+	MONT_MAC(t0, t1, t2, u[9], m[10]);
+	MONT_MAC(v0, v1, v2, u[10], m[9]);
+	MONT_MAC(w0, w1, w2, u[11], m[8]);
+	MONT_MAC(t0, t1, t2, u[12], m[7]);
+	MONT_MAC(v0, v1, v2, u[13], m[6]);
+	MONT_MAC(w0, w1, w2, u[14], m[5]);
+	MONT_MAC(t0, t1, t2, u[15], m[4]);
+	MONT_MAC(v0, v1, v2, u[16], m[3]);
+	MONT_MAC(w0, w1, w2, u[17], m[2]);
+	MONT_MAC(t0, t1, t2, u[18], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[19] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[19], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MUL(s0, s1, s2, a[0], a[20]);
+	MONT_MUL(c0, c1, c2, a[1], a[19]);
+	MONT_MAC(s0, s1, s2, a[2], a[18]);
+	MONT_MAC(c0, c1, c2, a[3], a[17]);
+	MONT_MAC(s0, s1, s2, a[4], a[16]);
+	MONT_MAC(c0, c1, c2, a[5], a[15]);
+	MONT_MAC(s0, s1, s2, a[6], a[14]);
+	MONT_MAC(c0, c1, c2, a[7], a[13]);
+	MONT_MAC(s0, s1, s2, a[8], a[12]);
+	MONT_MAC(c0, c1, c2, a[9], a[11]);
+	MONT_MAC(t0, t1, t2, a[10], a[10]);
+	MONT_MUL(v0, v1, v2, u[0], m[20]);
+	MONT_MUL(w0, w1, w2, u[1], m[19]);
+	MONT_MAC(t0, t1, t2, u[2], m[18]);
+	MONT_MAC(v0, v1, v2, u[3], m[17]);
+	MONT_MAC(w0, w1, w2, u[4], m[16]);
+	MONT_MAC(t0, t1, t2, u[5], m[15]);
+	MONT_MAC(v0, v1, v2, u[6], m[14]);
+	MONT_MAC(w0, w1, w2, u[7], m[13]);
+	MONT_MAC(t0, t1, t2, u[8], m[12]);
+	MONT_MAC(v0, v1, v2, u[9], m[11]);
+	MONT_MAC(w0, w1, w2, u[10], m[10]);
+	MONT_MAC(t0, t1, t2, u[11], m[9]);
+	MONT_MAC(v0, v1, v2, u[12], m[8]);
+	MONT_MAC(w0, w1, w2, u[13], m[7]);
+	MONT_MAC(t0, t1, t2, u[14], m[6]);
+	MONT_MAC(v0, v1, v2, u[15], m[5]);
+	MONT_MAC(w0, w1, w2, u[16], m[4]);
+	MONT_MAC(t0, t1, t2, u[17], m[3]);
+	MONT_MAC(v0, v1, v2, u[18], m[2]);
+	MONT_MAC(w0, w1, w2, u[19], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[20] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[20], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MUL(s0, s1, s2, a[0], a[21]);
+	MONT_MUL(c0, c1, c2, a[1], a[20]);
+	MONT_MAC(s0, s1, s2, a[2], a[19]);
+	MONT_MAC(c0, c1, c2, a[3], a[18]);
+	MONT_MAC(s0, s1, s2, a[4], a[17]);
+	MONT_MAC(c0, c1, c2, a[5], a[16]);
+	MONT_MAC(s0, s1, s2, a[6], a[15]);
+	MONT_MAC(c0, c1, c2, a[7], a[14]);
+	MONT_MAC(s0, s1, s2, a[8], a[13]);
+	MONT_MAC(c0, c1, c2, a[9], a[12]);
+	MONT_MAC(s0, s1, s2, a[10], a[11]);
+	MONT_MAC(t0, t1, t2, u[0], m[21]);
+	MONT_MUL(v0, v1, v2, u[1], m[20]);
+	MONT_MUL(w0, w1, w2, u[2], m[19]);
+	MONT_MAC(t0, t1, t2, u[3], m[18]);
+	MONT_MAC(v0, v1, v2, u[4], m[17]);
+	MONT_MAC(w0, w1, w2, u[5], m[16]);
+	MONT_MAC(t0, t1, t2, u[6], m[15]);
+	MONT_MAC(v0, v1, v2, u[7], m[14]);
+	MONT_MAC(w0, w1, w2, u[8], m[13]);
+	MONT_MAC(t0, t1, t2, u[9], m[12]);
+	MONT_MAC(v0, v1, v2, u[10], m[11]);
+	MONT_MAC(w0, w1, w2, u[11], m[10]);
+	MONT_MAC(t0, t1, t2, u[12], m[9]);
+	MONT_MAC(v0, v1, v2, u[13], m[8]);
+	MONT_MAC(w0, w1, w2, u[14], m[7]);
+	MONT_MAC(t0, t1, t2, u[15], m[6]);
+	MONT_MAC(v0, v1, v2, u[16], m[5]);
+	MONT_MAC(w0, w1, w2, u[17], m[4]);
+	MONT_MAC(t0, t1, t2, u[18], m[3]);
+	MONT_MAC(v0, v1, v2, u[19], m[2]);
+	MONT_MAC(w0, w1, w2, u[20], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[21] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[21], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MUL(s0, s1, s2, a[0], a[22]);
+	MONT_MUL(c0, c1, c2, a[1], a[21]);
+	MONT_MAC(s0, s1, s2, a[2], a[20]);
+	MONT_MAC(c0, c1, c2, a[3], a[19]);
+	MONT_MAC(s0, s1, s2, a[4], a[18]);
+	MONT_MAC(c0, c1, c2, a[5], a[17]);
+	MONT_MAC(s0, s1, s2, a[6], a[16]);
+	MONT_MAC(c0, c1, c2, a[7], a[15]);
+	MONT_MAC(s0, s1, s2, a[8], a[14]);
+	MONT_MAC(c0, c1, c2, a[9], a[13]);
+	MONT_MAC(s0, s1, s2, a[10], a[12]);
+	MONT_MAC(t0, t1, t2, a[11], a[11]);
+	MONT_MUL(v0, v1, v2, u[0], m[22]);
+	MONT_MUL(w0, w1, w2, u[1], m[21]);
+	MONT_MAC(t0, t1, t2, u[2], m[20]);
+	MONT_MAC(v0, v1, v2, u[3], m[19]);
+	MONT_MAC(w0, w1, w2, u[4], m[18]);
+	MONT_MAC(t0, t1, t2, u[5], m[17]);
+	MONT_MAC(v0, v1, v2, u[6], m[16]);
+	MONT_MAC(w0, w1, w2, u[7], m[15]);
+	MONT_MAC(t0, t1, t2, u[8], m[14]);
+	MONT_MAC(v0, v1, v2, u[9], m[13]);
+	MONT_MAC(w0, w1, w2, u[10], m[12]);
+	MONT_MAC(t0, t1, t2, u[11], m[11]);
+	MONT_MAC(v0, v1, v2, u[12], m[10]);
+	MONT_MAC(w0, w1, w2, u[13], m[9]);
+	MONT_MAC(t0, t1, t2, u[14], m[8]);
+	MONT_MAC(v0, v1, v2, u[15], m[7]);
+	MONT_MAC(w0, w1, w2, u[16], m[6]);
+	MONT_MAC(t0, t1, t2, u[17], m[5]);
+	MONT_MAC(v0, v1, v2, u[18], m[4]);
+	MONT_MAC(w0, w1, w2, u[19], m[3]);
+	MONT_MAC(t0, t1, t2, u[20], m[2]);
+	MONT_MAC(v0, v1, v2, u[21], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[22] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[22], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MUL(s0, s1, s2, a[0], a[23]);
+	MONT_MUL(c0, c1, c2, a[1], a[22]);
+	MONT_MAC(s0, s1, s2, a[2], a[21]);
+	MONT_MAC(c0, c1, c2, a[3], a[20]);
+	MONT_MAC(s0, s1, s2, a[4], a[19]);
+	MONT_MAC(c0, c1, c2, a[5], a[18]);
+	MONT_MAC(s0, s1, s2, a[6], a[17]);
+	MONT_MAC(c0, c1, c2, a[7], a[16]);
+	MONT_MAC(s0, s1, s2, a[8], a[15]);
+	MONT_MAC(c0, c1, c2, a[9], a[14]);
+	MONT_MAC(s0, s1, s2, a[10], a[13]);
+	MONT_MAC(c0, c1, c2, a[11], a[12]);
+	MONT_MAC(t0, t1, t2, u[0], m[23]);
+	MONT_MUL(v0, v1, v2, u[1], m[22]);
+	MONT_MUL(w0, w1, w2, u[2], m[21]);
+	MONT_MAC(t0, t1, t2, u[3], m[20]);
+	MONT_MAC(v0, v1, v2, u[4], m[19]);
+	MONT_MAC(w0, w1, w2, u[5], m[18]);
+	MONT_MAC(t0, t1, t2, u[6], m[17]);
+	MONT_MAC(v0, v1, v2, u[7], m[16]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_MAC(v0, v1, v2, u[16], m[7]);
+	MONT_MAC(w0, w1, w2, u[17], m[6]);
+	MONT_MAC(t0, t1, t2, u[18], m[5]);
+	MONT_MAC(v0, v1, v2, u[19], m[4]);
+	MONT_MAC(w0, w1, w2, u[20], m[3]);
+	MONT_MAC(t0, t1, t2, u[21], m[2]);
+	MONT_MAC(v0, v1, v2, u[22], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[23] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[23], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MUL(s0, s1, s2, a[0], a[24]);
+	MONT_MUL(c0, c1, c2, a[1], a[23]);
+	MONT_MAC(s0, s1, s2, a[2], a[22]);
+	MONT_MAC(c0, c1, c2, a[3], a[21]);
+	MONT_MAC(s0, s1, s2, a[4], a[20]);
+	MONT_MAC(c0, c1, c2, a[5], a[19]);
+	MONT_MAC(s0, s1, s2, a[6], a[18]);
+	MONT_MAC(c0, c1, c2, a[7], a[17]);
+	MONT_MAC(s0, s1, s2, a[8], a[16]);
+	MONT_MAC(c0, c1, c2, a[9], a[15]);
+	MONT_MAC(s0, s1, s2, a[10], a[14]);
+	MONT_MAC(c0, c1, c2, a[11], a[13]);
+	MONT_MAC(t0, t1, t2, a[12], a[12]);
+	MONT_MUL(v0, v1, v2, u[0], m[24]);
+	MONT_MUL(w0, w1, w2, u[1], m[23]);
+	MONT_MAC(t0, t1, t2, u[2], m[22]);
+	MONT_MAC(v0, v1, v2, u[3], m[21]);
+	MONT_MAC(w0, w1, w2, u[4], m[20]);
+	MONT_MAC(t0, t1, t2, u[5], m[19]);
+	MONT_MAC(v0, v1, v2, u[6], m[18]);
+	MONT_MAC(w0, w1, w2, u[7], m[17]);
+	MONT_MAC(t0, t1, t2, u[8], m[16]);
+	MONT_MAC(v0, v1, v2, u[9], m[15]);
+	MONT_MAC(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_MAC(w0, w1, w2, u[16], m[8]);
+	MONT_MAC(t0, t1, t2, u[17], m[7]);
+	MONT_MAC(v0, v1, v2, u[18], m[6]);
+	MONT_MAC(w0, w1, w2, u[19], m[5]);
+	MONT_MAC(t0, t1, t2, u[20], m[4]);
+	MONT_MAC(v0, v1, v2, u[21], m[3]);
+	MONT_MAC(w0, w1, w2, u[22], m[2]);
+	MONT_MAC(t0, t1, t2, u[23], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[24] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[24], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MUL(s0, s1, s2, a[0], a[25]);
+	MONT_MUL(c0, c1, c2, a[1], a[24]);
+	MONT_MAC(s0, s1, s2, a[2], a[23]);
+	MONT_MAC(c0, c1, c2, a[3], a[22]);
+	MONT_MAC(s0, s1, s2, a[4], a[21]);
+	MONT_MAC(c0, c1, c2, a[5], a[20]);
+	MONT_MAC(s0, s1, s2, a[6], a[19]);
+	MONT_MAC(c0, c1, c2, a[7], a[18]);
+	MONT_MAC(s0, s1, s2, a[8], a[17]);
+	MONT_MAC(c0, c1, c2, a[9], a[16]);
+	MONT_MAC(s0, s1, s2, a[10], a[15]);
+	MONT_MAC(c0, c1, c2, a[11], a[14]);
+	MONT_MAC(s0, s1, s2, a[12], a[13]);
+	MONT_MAC(t0, t1, t2, u[0], m[25]);
+	MONT_MUL(v0, v1, v2, u[1], m[24]);
+	MONT_MUL(w0, w1, w2, u[2], m[23]);
+	MONT_MAC(t0, t1, t2, u[3], m[22]);
+	MONT_MAC(v0, v1, v2, u[4], m[21]);
+	MONT_MAC(w0, w1, w2, u[5], m[20]);
+	MONT_MAC(t0, t1, t2, u[6], m[19]);
+	MONT_MAC(v0, v1, v2, u[7], m[18]);
+	MONT_MAC(w0, w1, w2, u[8], m[17]);
+	MONT_MAC(t0, t1, t2, u[9], m[16]);
+	MONT_MAC(v0, v1, v2, u[10], m[15]);
+	MONT_MAC(w0, w1, w2, u[11], m[14]);
+	MONT_MAC(t0, t1, t2, u[12], m[13]);
+	MONT_MAC(v0, v1, v2, u[13], m[12]);
+	MONT_MAC(w0, w1, w2, u[14], m[11]);
+	MONT_MAC(t0, t1, t2, u[15], m[10]);
+	MONT_MAC(v0, v1, v2, u[16], m[9]);
+	MONT_MAC(w0, w1, w2, u[17], m[8]);
+	MONT_MAC(t0, t1, t2, u[18], m[7]);
+	MONT_MAC(v0, v1, v2, u[19], m[6]);
+	MONT_MAC(w0, w1, w2, u[20], m[5]);
+	MONT_MAC(t0, t1, t2, u[21], m[4]);
+	MONT_MAC(v0, v1, v2, u[22], m[3]);
+	MONT_MAC(w0, w1, w2, u[23], m[2]);
+	MONT_MAC(t0, t1, t2, u[24], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[25] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[25], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MUL(s0, s1, s2, a[0], a[26]);
+	MONT_MUL(c0, c1, c2, a[1], a[25]);
+	MONT_MAC(s0, s1, s2, a[2], a[24]);
+	MONT_MAC(c0, c1, c2, a[3], a[23]);
+	MONT_MAC(s0, s1, s2, a[4], a[22]);
+	MONT_MAC(c0, c1, c2, a[5], a[21]);
+	MONT_MAC(s0, s1, s2, a[6], a[20]);
+	MONT_MAC(c0, c1, c2, a[7], a[19]);
+	MONT_MAC(s0, s1, s2, a[8], a[18]);
+	MONT_MAC(c0, c1, c2, a[9], a[17]);
+	MONT_MAC(s0, s1, s2, a[10], a[16]);
+	MONT_MAC(c0, c1, c2, a[11], a[15]);
+	MONT_MAC(s0, s1, s2, a[12], a[14]);
+	MONT_MAC(t0, t1, t2, a[13], a[13]);
+	MONT_MUL(v0, v1, v2, u[0], m[26]);
+	MONT_MUL(w0, w1, w2, u[1], m[25]);
+	MONT_MAC(t0, t1, t2, u[2], m[24]);
+	MONT_MAC(v0, v1, v2, u[3], m[23]);
+	MONT_MAC(w0, w1, w2, u[4], m[22]);
+	MONT_MAC(t0, t1, t2, u[5], m[21]);
+	MONT_MAC(v0, v1, v2, u[6], m[20]);
+	MONT_MAC(w0, w1, w2, u[7], m[19]);
+	MONT_MAC(t0, t1, t2, u[8], m[18]);
+	MONT_MAC(v0, v1, v2, u[9], m[17]);
+	MONT_MAC(w0, w1, w2, u[10], m[16]);
+	MONT_MAC(t0, t1, t2, u[11], m[15]);
+	MONT_MAC(v0, v1, v2, u[12], m[14]);
+	MONT_MAC(w0, w1, w2, u[13], m[13]);
+	MONT_MAC(t0, t1, t2, u[14], m[12]);
+	MONT_MAC(v0, v1, v2, u[15], m[11]);
+	MONT_MAC(w0, w1, w2, u[16], m[10]);
+	MONT_MAC(t0, t1, t2, u[17], m[9]);
+	MONT_MAC(v0, v1, v2, u[18], m[8]);
+	MONT_MAC(w0, w1, w2, u[19], m[7]);
+	MONT_MAC(t0, t1, t2, u[20], m[6]);
+	MONT_MAC(v0, v1, v2, u[21], m[5]);
+	MONT_MAC(w0, w1, w2, u[22], m[4]);
+	MONT_MAC(t0, t1, t2, u[23], m[3]);
+	MONT_MAC(v0, v1, v2, u[24], m[2]);
+	MONT_MAC(w0, w1, w2, u[25], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[26] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[26], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MUL(s0, s1, s2, a[0], a[27]);
+	MONT_MUL(c0, c1, c2, a[1], a[26]);
+	MONT_MAC(s0, s1, s2, a[2], a[25]);
+	MONT_MAC(c0, c1, c2, a[3], a[24]);
+	MONT_MAC(s0, s1, s2, a[4], a[23]);
+	MONT_MAC(c0, c1, c2, a[5], a[22]);
+	MONT_MAC(s0, s1, s2, a[6], a[21]);
+	MONT_MAC(c0, c1, c2, a[7], a[20]);
+	MONT_MAC(s0, s1, s2, a[8], a[19]);
+	MONT_MAC(c0, c1, c2, a[9], a[18]);
+	MONT_MAC(s0, s1, s2, a[10], a[17]);
+	MONT_MAC(c0, c1, c2, a[11], a[16]);
+	MONT_MAC(s0, s1, s2, a[12], a[15]);
+	MONT_MAC(c0, c1, c2, a[13], a[14]);
+	MONT_MAC(t0, t1, t2, u[0], m[27]);
+	MONT_MUL(v0, v1, v2, u[1], m[26]);
+	MONT_MUL(w0, w1, w2, u[2], m[25]);
+	MONT_MAC(t0, t1, t2, u[3], m[24]);
+	MONT_MAC(v0, v1, v2, u[4], m[23]);
+	MONT_MAC(w0, w1, w2, u[5], m[22]);
+	MONT_MAC(t0, t1, t2, u[6], m[21]);
+	MONT_MAC(v0, v1, v2, u[7], m[20]);
+	MONT_MAC(w0, w1, w2, u[8], m[19]);
+	MONT_MAC(t0, t1, t2, u[9], m[18]);
+	MONT_MAC(v0, v1, v2, u[10], m[17]);
+	MONT_MAC(w0, w1, w2, u[11], m[16]);
+	MONT_MAC(t0, t1, t2, u[12], m[15]);
+	MONT_MAC(v0, v1, v2, u[13], m[14]);
+	MONT_MAC(w0, w1, w2, u[14], m[13]);
+	MONT_MAC(t0, t1, t2, u[15], m[12]);
+	MONT_MAC(v0, v1, v2, u[16], m[11]);
+	MONT_MAC(w0, w1, w2, u[17], m[10]);
+	MONT_MAC(t0, t1, t2, u[18], m[9]);
+	MONT_MAC(v0, v1, v2, u[19], m[8]);
+	MONT_MAC(w0, w1, w2, u[20], m[7]);
+	MONT_MAC(t0, t1, t2, u[21], m[6]);
+	MONT_MAC(v0, v1, v2, u[22], m[5]);
+	MONT_MAC(w0, w1, w2, u[23], m[4]);
+	MONT_MAC(t0, t1, t2, u[24], m[3]);
+	MONT_MAC(v0, v1, v2, u[25], m[2]);
+	MONT_MAC(w0, w1, w2, u[26], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[27] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[27], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MUL(s0, s1, s2, a[0], a[28]);
+	MONT_MUL(c0, c1, c2, a[1], a[27]);
+	MONT_MAC(s0, s1, s2, a[2], a[26]);
+	MONT_MAC(c0, c1, c2, a[3], a[25]);
+	MONT_MAC(s0, s1, s2, a[4], a[24]);
+	MONT_MAC(c0, c1, c2, a[5], a[23]);
+	MONT_MAC(s0, s1, s2, a[6], a[22]);
+	MONT_MAC(c0, c1, c2, a[7], a[21]);
+	MONT_MAC(s0, s1, s2, a[8], a[20]);
+	MONT_MAC(c0, c1, c2, a[9], a[19]);
+	MONT_MAC(s0, s1, s2, a[10], a[18]);
+	MONT_MAC(c0, c1, c2, a[11], a[17]);
+	MONT_MAC(s0, s1, s2, a[12], a[16]);
+	MONT_MAC(c0, c1, c2, a[13], a[15]);
+	MONT_MAC(t0, t1, t2, a[14], a[14]);
+	MONT_MUL(v0, v1, v2, u[0], m[28]);
+	MONT_MUL(w0, w1, w2, u[1], m[27]);
+	MONT_MAC(t0, t1, t2, u[2], m[26]);
+	MONT_MAC(v0, v1, v2, u[3], m[25]);
+	MONT_MAC(w0, w1, w2, u[4], m[24]);
+	MONT_MAC(t0, t1, t2, u[5], m[23]);
+	MONT_MAC(v0, v1, v2, u[6], m[22]);
+	MONT_MAC(w0, w1, w2, u[7], m[21]);
+	MONT_MAC(t0, t1, t2, u[8], m[20]);
+	MONT_MAC(v0, v1, v2, u[9], m[19]);
+	MONT_MAC(w0, w1, w2, u[10], m[18]);
+	MONT_MAC(t0, t1, t2, u[11], m[17]);
+	MONT_MAC(v0, v1, v2, u[12], m[16]);
+	MONT_MAC(w0, w1, w2, u[13], m[15]);
+	MONT_MAC(t0, t1, t2, u[14], m[14]);
+	MONT_MAC(v0, v1, v2, u[15], m[13]);
+	MONT_MAC(w0, w1, w2, u[16], m[12]);
+	MONT_MAC(t0, t1, t2, u[17], m[11]);
+	MONT_MAC(v0, v1, v2, u[18], m[10]);
+	MONT_MAC(w0, w1, w2, u[19], m[9]);
+	MONT_MAC(t0, t1, t2, u[20], m[8]);
+	MONT_MAC(v0, v1, v2, u[21], m[7]);
+	MONT_MAC(w0, w1, w2, u[22], m[6]);
+	MONT_MAC(t0, t1, t2, u[23], m[5]);
+	MONT_MAC(v0, v1, v2, u[24], m[4]);
+	MONT_MAC(w0, w1, w2, u[25], m[3]);
+	MONT_MAC(t0, t1, t2, u[26], m[2]);
+	MONT_MAC(v0, v1, v2, u[27], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[28] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[28], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MUL(s0, s1, s2, a[0], a[29]);
+	MONT_MUL(c0, c1, c2, a[1], a[28]);
+	MONT_MAC(s0, s1, s2, a[2], a[27]);
+	MONT_MAC(c0, c1, c2, a[3], a[26]);
+	MONT_MAC(s0, s1, s2, a[4], a[25]);
+	MONT_MAC(c0, c1, c2, a[5], a[24]);
+	MONT_MAC(s0, s1, s2, a[6], a[23]);
+	MONT_MAC(c0, c1, c2, a[7], a[22]);
+	MONT_MAC(s0, s1, s2, a[8], a[21]);
+	MONT_MAC(c0, c1, c2, a[9], a[20]);
+	MONT_MAC(s0, s1, s2, a[10], a[19]);
+	MONT_MAC(c0, c1, c2, a[11], a[18]);
+	MONT_MAC(s0, s1, s2, a[12], a[17]);
+	MONT_MAC(c0, c1, c2, a[13], a[16]);
+	MONT_MAC(s0, s1, s2, a[14], a[15]);
+	MONT_MAC(t0, t1, t2, u[0], m[29]);
+	MONT_MUL(v0, v1, v2, u[1], m[28]);
+	MONT_MUL(w0, w1, w2, u[2], m[27]);
+	MONT_MAC(t0, t1, t2, u[3], m[26]);
+	MONT_MAC(v0, v1, v2, u[4], m[25]);
+	MONT_MAC(w0, w1, w2, u[5], m[24]);
+	MONT_MAC(t0, t1, t2, u[6], m[23]);
+	MONT_MAC(v0, v1, v2, u[7], m[22]);
+	MONT_MAC(w0, w1, w2, u[8], m[21]);
+	MONT_MAC(t0, t1, t2, u[9], m[20]);
+	MONT_MAC(v0, v1, v2, u[10], m[19]);
+	MONT_MAC(w0, w1, w2, u[11], m[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[17]);
+	MONT_MAC(v0, v1, v2, u[13], m[16]);
+	MONT_MAC(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_MAC(v0, v1, v2, u[16], m[13]);
+	MONT_MAC(w0, w1, w2, u[17], m[12]);
+	MONT_MAC(t0, t1, t2, u[18], m[11]);
+	MONT_MAC(v0, v1, v2, u[19], m[10]);
+	MONT_MAC(w0, w1, w2, u[20], m[9]);
+	MONT_MAC(t0, t1, t2, u[21], m[8]);
+	MONT_MAC(v0, v1, v2, u[22], m[7]);
+	MONT_MAC(w0, w1, w2, u[23], m[6]);
+	MONT_MAC(t0, t1, t2, u[24], m[5]);
+	MONT_MAC(v0, v1, v2, u[25], m[4]);
+	MONT_MAC(w0, w1, w2, u[26], m[3]);
+	MONT_MAC(t0, t1, t2, u[27], m[2]);
+	MONT_MAC(v0, v1, v2, u[28], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[29] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[29], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MUL(s0, s1, s2, a[0], a[30]);
+	MONT_MUL(c0, c1, c2, a[1], a[29]);
+	MONT_MAC(s0, s1, s2, a[2], a[28]);
+	MONT_MAC(c0, c1, c2, a[3], a[27]);
+	MONT_MAC(s0, s1, s2, a[4], a[26]);
+	MONT_MAC(c0, c1, c2, a[5], a[25]);
+	MONT_MAC(s0, s1, s2, a[6], a[24]);
+	MONT_MAC(c0, c1, c2, a[7], a[23]);
+	MONT_MAC(s0, s1, s2, a[8], a[22]);
+	MONT_MAC(c0, c1, c2, a[9], a[21]);
+	MONT_MAC(s0, s1, s2, a[10], a[20]);
+	MONT_MAC(c0, c1, c2, a[11], a[19]);
+	MONT_MAC(s0, s1, s2, a[12], a[18]);
+	MONT_MAC(c0, c1, c2, a[13], a[17]);
+	MONT_MAC(s0, s1, s2, a[14], a[16]);
+	MONT_MAC(t0, t1, t2, a[15], a[15]);
+	MONT_MUL(v0, v1, v2, u[0], m[30]);
+	MONT_MUL(w0, w1, w2, u[1], m[29]);
+	MONT_MAC(t0, t1, t2, u[2], m[28]);
+	MONT_MAC(v0, v1, v2, u[3], m[27]);
+	MONT_MAC(w0, w1, w2, u[4], m[26]);
+	MONT_MAC(t0, t1, t2, u[5], m[25]);
+	MONT_MAC(v0, v1, v2, u[6], m[24]);
+	MONT_MAC(w0, w1, w2, u[7], m[23]);
+	MONT_MAC(t0, t1, t2, u[8], m[22]);
+	MONT_MAC(v0, v1, v2, u[9], m[21]);
+	MONT_MAC(w0, w1, w2, u[10], m[20]);
+	MONT_MAC(t0, t1, t2, u[11], m[19]);
+	MONT_MAC(v0, v1, v2, u[12], m[18]);
+	MONT_MAC(w0, w1, w2, u[13], m[17]);
+	MONT_MAC(t0, t1, t2, u[14], m[16]);
+	MONT_MAC(v0, v1, v2, u[15], m[15]);
+	MONT_MAC(w0, w1, w2, u[16], m[14]);
+	MONT_MAC(t0, t1, t2, u[17], m[13]);
+	MONT_MAC(v0, v1, v2, u[18], m[12]);
+	MONT_MAC(w0, w1, w2, u[19], m[11]);
+	MONT_MAC(t0, t1, t2, u[20], m[10]);
+	MONT_MAC(v0, v1, v2, u[21], m[9]);
+	MONT_MAC(w0, w1, w2, u[22], m[8]);
+	MONT_MAC(t0, t1, t2, u[23], m[7]);
+	MONT_MAC(v0, v1, v2, u[24], m[6]);
+	MONT_MAC(w0, w1, w2, u[25], m[5]);
+	MONT_MAC(t0, t1, t2, u[26], m[4]);
+	MONT_MAC(v0, v1, v2, u[27], m[3]);
+	MONT_MAC(w0, w1, w2, u[28], m[2]);
+	MONT_MAC(t0, t1, t2, u[29], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[30] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[30], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 31 */
+	MONT_MUL(s0, s1, s2, a[0], a[31]);
+	MONT_MUL(c0, c1, c2, a[1], a[30]);
+	MONT_MAC(s0, s1, s2, a[2], a[29]);
+	MONT_MAC(c0, c1, c2, a[3], a[28]);
+	MONT_MAC(s0, s1, s2, a[4], a[27]);
+	MONT_MAC(c0, c1, c2, a[5], a[26]);
+	MONT_MAC(s0, s1, s2, a[6], a[25]);
+	MONT_MAC(c0, c1, c2, a[7], a[24]);
+	MONT_MAC(s0, s1, s2, a[8], a[23]);
+	MONT_MAC(c0, c1, c2, a[9], a[22]);
+	MONT_MAC(s0, s1, s2, a[10], a[21]);
+	MONT_MAC(c0, c1, c2, a[11], a[20]);
+	MONT_MAC(s0, s1, s2, a[12], a[19]);
+	MONT_MAC(c0, c1, c2, a[13], a[18]);
+	MONT_MAC(s0, s1, s2, a[14], a[17]);
+	MONT_MAC(c0, c1, c2, a[15], a[16]);
+	MONT_MAC(t0, t1, t2, u[0], m[31]);
+	MONT_MUL(v0, v1, v2, u[1], m[30]);
+	MONT_MUL(w0, w1, w2, u[2], m[29]);
+	MONT_MAC(t0, t1, t2, u[3], m[28]);
+	MONT_MAC(v0, v1, v2, u[4], m[27]);
+	MONT_MAC(w0, w1, w2, u[5], m[26]);
+	MONT_MAC(t0, t1, t2, u[6], m[25]);
+	MONT_MAC(v0, v1, v2, u[7], m[24]);
+	MONT_MAC(w0, w1, w2, u[8], m[23]);
+	MONT_MAC(t0, t1, t2, u[9], m[22]);
+	MONT_MAC(v0, v1, v2, u[10], m[21]);
+	MONT_MAC(w0, w1, w2, u[11], m[20]);
+	MONT_MAC(t0, t1, t2, u[12], m[19]);
+	MONT_MAC(v0, v1, v2, u[13], m[18]);
+	MONT_MAC(w0, w1, w2, u[14], m[17]);
+	MONT_MAC(t0, t1, t2, u[15], m[16]);
+	MONT_MAC(v0, v1, v2, u[16], m[15]);
+	MONT_MAC(w0, w1, w2, u[17], m[14]);
+	MONT_MAC(t0, t1, t2, u[18], m[13]);
+	MONT_MAC(v0, v1, v2, u[19], m[12]);
+	MONT_MAC(w0, w1, w2, u[20], m[11]);
+	MONT_MAC(t0, t1, t2, u[21], m[10]);
+	MONT_MAC(v0, v1, v2, u[22], m[9]);
+	MONT_MAC(w0, w1, w2, u[23], m[8]);
+	MONT_MAC(t0, t1, t2, u[24], m[7]);
+	MONT_MAC(v0, v1, v2, u[25], m[6]);
+	MONT_MAC(w0, w1, w2, u[26], m[5]);
+	MONT_MAC(t0, t1, t2, u[27], m[4]);
+	MONT_MAC(v0, v1, v2, u[28], m[3]);
+	MONT_MAC(w0, w1, w2, u[29], m[2]);
+	MONT_MAC(t0, t1, t2, u[30], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[31] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[31], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 32 */
+	MONT_MUL(s0, s1, s2, a[1], a[31]);
+	MONT_MUL(c0, c1, c2, a[2], a[30]);
+	MONT_MAC(s0, s1, s2, a[3], a[29]);
+	MONT_MAC(c0, c1, c2, a[4], a[28]);
+	MONT_MAC(s0, s1, s2, a[5], a[27]);
+	MONT_MAC(c0, c1, c2, a[6], a[26]);
+	MONT_MAC(s0, s1, s2, a[7], a[25]);
+	MONT_MAC(c0, c1, c2, a[8], a[24]);
+	MONT_MAC(s0, s1, s2, a[9], a[23]);
+	MONT_MAC(c0, c1, c2, a[10], a[22]);
+	MONT_MAC(s0, s1, s2, a[11], a[21]);
+	MONT_MAC(c0, c1, c2, a[12], a[20]);
+	MONT_MAC(s0, s1, s2, a[13], a[19]);
+	MONT_MAC(c0, c1, c2, a[14], a[18]);
+	MONT_MAC(s0, s1, s2, a[15], a[17]);
+	MONT_MAC(t0, t1, t2, a[16], a[16]);
+	MONT_MUL(v0, v1, v2, u[1], m[31]);
+	MONT_MUL(w0, w1, w2, u[2], m[30]);
+	MONT_MAC(t0, t1, t2, u[3], m[29]);
+	MONT_MAC(v0, v1, v2, u[4], m[28]);
+	MONT_MAC(w0, w1, w2, u[5], m[27]);
+	MONT_MAC(t0, t1, t2, u[6], m[26]);
+	MONT_MAC(v0, v1, v2, u[7], m[25]);
+	MONT_MAC(w0, w1, w2, u[8], m[24]);
+	MONT_MAC(t0, t1, t2, u[9], m[23]);
+	MONT_MAC(v0, v1, v2, u[10], m[22]);
+	MONT_MAC(w0, w1, w2, u[11], m[21]);
+	MONT_MAC(t0, t1, t2, u[12], m[20]);
+	MONT_MAC(v0, v1, v2, u[13], m[19]);
+	MONT_MAC(w0, w1, w2, u[14], m[18]);
+	MONT_MAC(t0, t1, t2, u[15], m[17]);
+	MONT_MAC(v0, v1, v2, u[16], m[16]);
+	MONT_MAC(w0, w1, w2, u[17], m[15]);
+	MONT_MAC(t0, t1, t2, u[18], m[14]);
+	MONT_MAC(v0, v1, v2, u[19], m[13]);
+	MONT_MAC(w0, w1, w2, u[20], m[12]);
+	MONT_MAC(t0, t1, t2, u[21], m[11]);
+	MONT_MAC(v0, v1, v2, u[22], m[10]);
+	MONT_MAC(w0, w1, w2, u[23], m[9]);
+	MONT_MAC(t0, t1, t2, u[24], m[8]);
+	MONT_MAC(v0, v1, v2, u[25], m[7]);
+	MONT_MAC(w0, w1, w2, u[26], m[6]);
+	MONT_MAC(t0, t1, t2, u[27], m[5]);
+	MONT_MAC(v0, v1, v2, u[28], m[4]);
+	MONT_MAC(w0, w1, w2, u[29], m[3]);
+	MONT_MAC(t0, t1, t2, u[30], m[2]);
+	MONT_MAC(v0, v1, v2, u[31], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 33 */
+	MONT_MUL(s0, s1, s2, a[2], a[31]);
+	MONT_MUL(c0, c1, c2, a[3], a[30]);
+	MONT_MAC(s0, s1, s2, a[4], a[29]);
+	MONT_MAC(c0, c1, c2, a[5], a[28]);
+	MONT_MAC(s0, s1, s2, a[6], a[27]);
+	MONT_MAC(c0, c1, c2, a[7], a[26]);
+	MONT_MAC(s0, s1, s2, a[8], a[25]);
+	MONT_MAC(c0, c1, c2, a[9], a[24]);
+	MONT_MAC(s0, s1, s2, a[10], a[23]);
+	MONT_MAC(c0, c1, c2, a[11], a[22]);
+	MONT_MAC(s0, s1, s2, a[12], a[21]);
+	MONT_MAC(c0, c1, c2, a[13], a[20]);
+	MONT_MAC(s0, s1, s2, a[14], a[19]);
+	MONT_MAC(c0, c1, c2, a[15], a[18]);
+	MONT_MAC(s0, s1, s2, a[16], a[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[31]);
+	MONT_MUL(v0, v1, v2, u[3], m[30]);
+	MONT_MUL(w0, w1, w2, u[4], m[29]);
+	MONT_MAC(t0, t1, t2, u[5], m[28]);
+	MONT_MAC(v0, v1, v2, u[6], m[27]);
+	MONT_MAC(w0, w1, w2, u[7], m[26]);
+	MONT_MAC(t0, t1, t2, u[8], m[25]);
+	MONT_MAC(v0, v1, v2, u[9], m[24]);
+	MONT_MAC(w0, w1, w2, u[10], m[23]);
+	MONT_MAC(t0, t1, t2, u[11], m[22]);
+	MONT_MAC(v0, v1, v2, u[12], m[21]);
+	MONT_MAC(w0, w1, w2, u[13], m[20]);
+	MONT_MAC(t0, t1, t2, u[14], m[19]);
+	MONT_MAC(v0, v1, v2, u[15], m[18]);
+	MONT_MAC(w0, w1, w2, u[16], m[17]);
+	MONT_MAC(t0, t1, t2, u[17], m[16]);
+	MONT_MAC(v0, v1, v2, u[18], m[15]);
+	MONT_MAC(w0, w1, w2, u[19], m[14]);
+	MONT_MAC(t0, t1, t2, u[20], m[13]);
+	MONT_MAC(v0, v1, v2, u[21], m[12]);
+	MONT_MAC(w0, w1, w2, u[22], m[11]);
+	MONT_MAC(t0, t1, t2, u[23], m[10]);
+	MONT_MAC(v0, v1, v2, u[24], m[9]);
+	MONT_MAC(w0, w1, w2, u[25], m[8]);
+	MONT_MAC(t0, t1, t2, u[26], m[7]);
+	MONT_MAC(v0, v1, v2, u[27], m[6]);
+	MONT_MAC(w0, w1, w2, u[28], m[5]);
+	MONT_MAC(t0, t1, t2, u[29], m[4]);
+	MONT_MAC(v0, v1, v2, u[30], m[3]);
+	MONT_MAC(w0, w1, w2, u[31], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 34 */
+	MONT_MUL(s0, s1, s2, a[3], a[31]);
+	MONT_MUL(c0, c1, c2, a[4], a[30]);
+	MONT_MAC(s0, s1, s2, a[5], a[29]);
+	MONT_MAC(c0, c1, c2, a[6], a[28]);
+	MONT_MAC(s0, s1, s2, a[7], a[27]);
+	MONT_MAC(c0, c1, c2, a[8], a[26]);
+	MONT_MAC(s0, s1, s2, a[9], a[25]);
+	MONT_MAC(c0, c1, c2, a[10], a[24]);
+	MONT_MAC(s0, s1, s2, a[11], a[23]);
+	MONT_MAC(c0, c1, c2, a[12], a[22]);
+	MONT_MAC(s0, s1, s2, a[13], a[21]);
+	MONT_MAC(c0, c1, c2, a[14], a[20]);
+	MONT_MAC(s0, s1, s2, a[15], a[19]);
+	MONT_MAC(c0, c1, c2, a[16], a[18]);
+	MONT_MAC(t0, t1, t2, a[17], a[17]);
+	MONT_MUL(v0, v1, v2, u[3], m[31]);
+	MONT_MUL(w0, w1, w2, u[4], m[30]);
+	MONT_MAC(t0, t1, t2, u[5], m[29]);
+	MONT_MAC(v0, v1, v2, u[6], m[28]);
+	MONT_MAC(w0, w1, w2, u[7], m[27]);
+	MONT_MAC(t0, t1, t2, u[8], m[26]);
+	MONT_MAC(v0, v1, v2, u[9], m[25]);
+	MONT_MAC(w0, w1, w2, u[10], m[24]);
+	MONT_MAC(t0, t1, t2, u[11], m[23]);
+	MONT_MAC(v0, v1, v2, u[12], m[22]);
+	MONT_MAC(w0, w1, w2, u[13], m[21]);
+	MONT_MAC(t0, t1, t2, u[14], m[20]);
+	MONT_MAC(v0, v1, v2, u[15], m[19]);
+	MONT_MAC(w0, w1, w2, u[16], m[18]);
+	MONT_MAC(t0, t1, t2, u[17], m[17]);
+	MONT_MAC(v0, v1, v2, u[18], m[16]);
+	MONT_MAC(w0, w1, w2, u[19], m[15]);
+	MONT_MAC(t0, t1, t2, u[20], m[14]);
+	MONT_MAC(v0, v1, v2, u[21], m[13]);
+	MONT_MAC(w0, w1, w2, u[22], m[12]);
+	MONT_MAC(t0, t1, t2, u[23], m[11]);
+	MONT_MAC(v0, v1, v2, u[24], m[10]);
+	MONT_MAC(w0, w1, w2, u[25], m[9]);
+	MONT_MAC(t0, t1, t2, u[26], m[8]);
+	MONT_MAC(v0, v1, v2, u[27], m[7]);
+	MONT_MAC(w0, w1, w2, u[28], m[6]);
+	MONT_MAC(t0, t1, t2, u[29], m[5]);
+	MONT_MAC(v0, v1, v2, u[30], m[4]);
+	MONT_MAC(w0, w1, w2, u[31], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 35 */
+	MONT_MUL(s0, s1, s2, a[4], a[31]);
+	MONT_MUL(c0, c1, c2, a[5], a[30]);
+	MONT_MAC(s0, s1, s2, a[6], a[29]);
+	MONT_MAC(c0, c1, c2, a[7], a[28]);
+	MONT_MAC(s0, s1, s2, a[8], a[27]);
+	MONT_MAC(c0, c1, c2, a[9], a[26]);
+	MONT_MAC(s0, s1, s2, a[10], a[25]);
+	MONT_MAC(c0, c1, c2, a[11], a[24]);
+	MONT_MAC(s0, s1, s2, a[12], a[23]);
+	MONT_MAC(c0, c1, c2, a[13], a[22]);
+	MONT_MAC(s0, s1, s2, a[14], a[21]);
+	MONT_MAC(c0, c1, c2, a[15], a[20]);
+	MONT_MAC(s0, s1, s2, a[16], a[19]);
+	MONT_MAC(c0, c1, c2, a[17], a[18]);
+	MONT_MAC(t0, t1, t2, u[4], m[31]);
+	MONT_MUL(v0, v1, v2, u[5], m[30]);
+	MONT_MUL(w0, w1, w2, u[6], m[29]);
+	MONT_MAC(t0, t1, t2, u[7], m[28]);
+	MONT_MAC(v0, v1, v2, u[8], m[27]);
+	MONT_MAC(w0, w1, w2, u[9], m[26]);
+	MONT_MAC(t0, t1, t2, u[10], m[25]);
+	MONT_MAC(v0, v1, v2, u[11], m[24]);
+	MONT_MAC(w0, w1, w2, u[12], m[23]);
+	MONT_MAC(t0, t1, t2, u[13], m[22]);
+	MONT_MAC(v0, v1, v2, u[14], m[21]);
+	MONT_MAC(w0, w1, w2, u[15], m[20]);
+	MONT_MAC(t0, t1, t2, u[16], m[19]);
+	MONT_MAC(v0, v1, v2, u[17], m[18]);
+	MONT_MAC(w0, w1, w2, u[18], m[17]);
+	MONT_MAC(t0, t1, t2, u[19], m[16]);
+	MONT_MAC(v0, v1, v2, u[20], m[15]);
+	MONT_MAC(w0, w1, w2, u[21], m[14]);
+	MONT_MAC(t0, t1, t2, u[22], m[13]);
+	MONT_MAC(v0, v1, v2, u[23], m[12]);
+	MONT_MAC(w0, w1, w2, u[24], m[11]);
+	MONT_MAC(t0, t1, t2, u[25], m[10]);
+	MONT_MAC(v0, v1, v2, u[26], m[9]);
+	MONT_MAC(w0, w1, w2, u[27], m[8]);
+	MONT_MAC(t0, t1, t2, u[28], m[7]);
+	MONT_MAC(v0, v1, v2, u[29], m[6]);
+	MONT_MAC(w0, w1, w2, u[30], m[5]);
+	MONT_MAC(t0, t1, t2, u[31], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 36 */
+	MONT_MUL(s0, s1, s2, a[5], a[31]);
+	MONT_MUL(c0, c1, c2, a[6], a[30]);
+	MONT_MAC(s0, s1, s2, a[7], a[29]);
+	MONT_MAC(c0, c1, c2, a[8], a[28]);
+	MONT_MAC(s0, s1, s2, a[9], a[27]);
+	MONT_MAC(c0, c1, c2, a[10], a[26]);
+	MONT_MAC(s0, s1, s2, a[11], a[25]);
+	MONT_MAC(c0, c1, c2, a[12], a[24]);
+	MONT_MAC(s0, s1, s2, a[13], a[23]);
+	MONT_MAC(c0, c1, c2, a[14], a[22]);
+	MONT_MAC(s0, s1, s2, a[15], a[21]);
+	MONT_MAC(c0, c1, c2, a[16], a[20]);
+	MONT_MAC(s0, s1, s2, a[17], a[19]);
+	MONT_MAC(t0, t1, t2, a[18], a[18]);
+	MONT_MUL(v0, v1, v2, u[5], m[31]);
+	MONT_MUL(w0, w1, w2, u[6], m[30]);
+	MONT_MAC(t0, t1, t2, u[7], m[29]);
+	MONT_MAC(v0, v1, v2, u[8], m[28]);
+	MONT_MAC(w0, w1, w2, u[9], m[27]);
+	MONT_MAC(t0, t1, t2, u[10], m[26]);
+	MONT_MAC(v0, v1, v2, u[11], m[25]);
+	MONT_MAC(w0, w1, w2, u[12], m[24]);
+	MONT_MAC(t0, t1, t2, u[13], m[23]);
+	MONT_MAC(v0, v1, v2, u[14], m[22]);
+	MONT_MAC(w0, w1, w2, u[15], m[21]);
+	MONT_MAC(t0, t1, t2, u[16], m[20]);
+	MONT_MAC(v0, v1, v2, u[17], m[19]);
+	MONT_MAC(w0, w1, w2, u[18], m[18]);
+	MONT_MAC(t0, t1, t2, u[19], m[17]);
+	MONT_MAC(v0, v1, v2, u[20], m[16]);
+	MONT_MAC(w0, w1, w2, u[21], m[15]);
+	MONT_MAC(t0, t1, t2, u[22], m[14]);
+	MONT_MAC(v0, v1, v2, u[23], m[13]);
+	MONT_MAC(w0, w1, w2, u[24], m[12]);
+	MONT_MAC(t0, t1, t2, u[25], m[11]);
+	MONT_MAC(v0, v1, v2, u[26], m[10]);
+	MONT_MAC(w0, w1, w2, u[27], m[9]);
+	MONT_MAC(t0, t1, t2, u[28], m[8]);
+	MONT_MAC(v0, v1, v2, u[29], m[7]);
+	MONT_MAC(w0, w1, w2, u[30], m[6]);
+	MONT_MAC(t0, t1, t2, u[31], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 37 */
+	MONT_MUL(s0, s1, s2, a[6], a[31]);
+	MONT_MUL(c0, c1, c2, a[7], a[30]);
+	MONT_MAC(s0, s1, s2, a[8], a[29]);
+	MONT_MAC(c0, c1, c2, a[9], a[28]);
+	MONT_MAC(s0, s1, s2, a[10], a[27]);
+	MONT_MAC(c0, c1, c2, a[11], a[26]);
+	MONT_MAC(s0, s1, s2, a[12], a[25]);
+	MONT_MAC(c0, c1, c2, a[13], a[24]);
+	MONT_MAC(s0, s1, s2, a[14], a[23]);
+	MONT_MAC(c0, c1, c2, a[15], a[22]);
+	MONT_MAC(s0, s1, s2, a[16], a[21]);
+	MONT_MAC(c0, c1, c2, a[17], a[20]);
+	MONT_MAC(s0, s1, s2, a[18], a[19]);
+	MONT_MAC(t0, t1, t2, u[6], m[31]);
+	MONT_MUL(v0, v1, v2, u[7], m[30]);
+	MONT_MUL(w0, w1, w2, u[8], m[29]);
+	MONT_MAC(t0, t1, t2, u[9], m[28]);
+	MONT_MAC(v0, v1, v2, u[10], m[27]);
+	MONT_MAC(w0, w1, w2, u[11], m[26]);
+	MONT_MAC(t0, t1, t2, u[12], m[25]);
+	MONT_MAC(v0, v1, v2, u[13], m[24]);
+	MONT_MAC(w0, w1, w2, u[14], m[23]);
+	MONT_MAC(t0, t1, t2, u[15], m[22]);
+	MONT_MAC(v0, v1, v2, u[16], m[21]);
+	MONT_MAC(w0, w1, w2, u[17], m[20]);
+	MONT_MAC(t0, t1, t2, u[18], m[19]);
+	MONT_MAC(v0, v1, v2, u[19], m[18]);
+	MONT_MAC(w0, w1, w2, u[20], m[17]);
+	MONT_MAC(t0, t1, t2, u[21], m[16]);
+	MONT_MAC(v0, v1, v2, u[22], m[15]);
+	MONT_MAC(w0, w1, w2, u[23], m[14]);
+	MONT_MAC(t0, t1, t2, u[24], m[13]);
+	MONT_MAC(v0, v1, v2, u[25], m[12]);
+	MONT_MAC(w0, w1, w2, u[26], m[11]);
+	MONT_MAC(t0, t1, t2, u[27], m[10]);
+	MONT_MAC(v0, v1, v2, u[28], m[9]);
+	MONT_MAC(w0, w1, w2, u[29], m[8]);
+	MONT_MAC(t0, t1, t2, u[30], m[7]);
+	MONT_MAC(v0, v1, v2, u[31], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 38 */
+	MONT_MUL(s0, s1, s2, a[7], a[31]);
+	MONT_MUL(c0, c1, c2, a[8], a[30]);
+	MONT_MAC(s0, s1, s2, a[9], a[29]);
+	MONT_MAC(c0, c1, c2, a[10], a[28]);
+	MONT_MAC(s0, s1, s2, a[11], a[27]);
+	MONT_MAC(c0, c1, c2, a[12], a[26]);
+	MONT_MAC(s0, s1, s2, a[13], a[25]);
+	MONT_MAC(c0, c1, c2, a[14], a[24]);
+	MONT_MAC(s0, s1, s2, a[15], a[23]);
+	MONT_MAC(c0, c1, c2, a[16], a[22]);
+	MONT_MAC(s0, s1, s2, a[17], a[21]);
+	MONT_MAC(c0, c1, c2, a[18], a[20]);
+	MONT_MAC(t0, t1, t2, a[19], a[19]);
+	MONT_MUL(v0, v1, v2, u[7], m[31]);
+	MONT_MUL(w0, w1, w2, u[8], m[30]);
+	MONT_MAC(t0, t1, t2, u[9], m[29]);
+	MONT_MAC(v0, v1, v2, u[10], m[28]);
+	MONT_MAC(w0, w1, w2, u[11], m[27]);
+	MONT_MAC(t0, t1, t2, u[12], m[26]);
+	MONT_MAC(v0, v1, v2, u[13], m[25]);
+	MONT_MAC(w0, w1, w2, u[14], m[24]);
+	MONT_MAC(t0, t1, t2, u[15], m[23]);
+	MONT_MAC(v0, v1, v2, u[16], m[22]);
+	MONT_MAC(w0, w1, w2, u[17], m[21]);
+	MONT_MAC(t0, t1, t2, u[18], m[20]);
+	MONT_MAC(v0, v1, v2, u[19], m[19]);
+	MONT_MAC(w0, w1, w2, u[20], m[18]);
+	MONT_MAC(t0, t1, t2, u[21], m[17]);
+	MONT_MAC(v0, v1, v2, u[22], m[16]);
+	MONT_MAC(w0, w1, w2, u[23], m[15]);
+	MONT_MAC(t0, t1, t2, u[24], m[14]);
+	MONT_MAC(v0, v1, v2, u[25], m[13]);
+	MONT_MAC(w0, w1, w2, u[26], m[12]);
+	MONT_MAC(t0, t1, t2, u[27], m[11]);
+	MONT_MAC(v0, v1, v2, u[28], m[10]);
+	MONT_MAC(w0, w1, w2, u[29], m[9]);
+	MONT_MAC(t0, t1, t2, u[30], m[8]);
+	MONT_MAC(v0, v1, v2, u[31], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 39 */
+	MONT_MUL(s0, s1, s2, a[8], a[31]);
+	MONT_MUL(c0, c1, c2, a[9], a[30]);
+	MONT_MAC(s0, s1, s2, a[10], a[29]);
+	MONT_MAC(c0, c1, c2, a[11], a[28]);
+	MONT_MAC(s0, s1, s2, a[12], a[27]);
+	MONT_MAC(c0, c1, c2, a[13], a[26]);
+	MONT_MAC(s0, s1, s2, a[14], a[25]);
+	MONT_MAC(c0, c1, c2, a[15], a[24]);
+	MONT_MAC(s0, s1, s2, a[16], a[23]);
+	MONT_MAC(c0, c1, c2, a[17], a[22]);
+	MONT_MAC(s0, s1, s2, a[18], a[21]);
+	MONT_MAC(c0, c1, c2, a[19], a[20]);
+	MONT_MAC(t0, t1, t2, u[8], m[31]);
+	MONT_MUL(v0, v1, v2, u[9], m[30]);
+	MONT_MUL(w0, w1, w2, u[10], m[29]);
+	MONT_MAC(t0, t1, t2, u[11], m[28]);
+	MONT_MAC(v0, v1, v2, u[12], m[27]);
+	MONT_MAC(w0, w1, w2, u[13], m[26]);
+	MONT_MAC(t0, t1, t2, u[14], m[25]);
+	MONT_MAC(v0, v1, v2, u[15], m[24]);
+	MONT_MAC(w0, w1, w2, u[16], m[23]);
+	MONT_MAC(t0, t1, t2, u[17], m[22]);
+	MONT_MAC(v0, v1, v2, u[18], m[21]);
+	MONT_MAC(w0, w1, w2, u[19], m[20]);
+	MONT_MAC(t0, t1, t2, u[20], m[19]);
+	MONT_MAC(v0, v1, v2, u[21], m[18]);
+	MONT_MAC(w0, w1, w2, u[22], m[17]);
+	MONT_MAC(t0, t1, t2, u[23], m[16]);
+	MONT_MAC(v0, v1, v2, u[24], m[15]);
+	MONT_MAC(w0, w1, w2, u[25], m[14]);
+	MONT_MAC(t0, t1, t2, u[26], m[13]);
+	MONT_MAC(v0, v1, v2, u[27], m[12]);
+	MONT_MAC(w0, w1, w2, u[28], m[11]);
+	MONT_MAC(t0, t1, t2, u[29], m[10]);
+	MONT_MAC(v0, v1, v2, u[30], m[9]);
+	MONT_MAC(w0, w1, w2, u[31], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 40 */
+	MONT_MUL(s0, s1, s2, a[9], a[31]);
+	MONT_MUL(c0, c1, c2, a[10], a[30]);
+	MONT_MAC(s0, s1, s2, a[11], a[29]);
+	MONT_MAC(c0, c1, c2, a[12], a[28]);
+	MONT_MAC(s0, s1, s2, a[13], a[27]);
+	MONT_MAC(c0, c1, c2, a[14], a[26]);
+	MONT_MAC(s0, s1, s2, a[15], a[25]);
+	MONT_MAC(c0, c1, c2, a[16], a[24]);
+	MONT_MAC(s0, s1, s2, a[17], a[23]);
+	MONT_MAC(c0, c1, c2, a[18], a[22]);
+	MONT_MAC(s0, s1, s2, a[19], a[21]);
+	MONT_MAC(t0, t1, t2, a[20], a[20]);
+	MONT_MUL(v0, v1, v2, u[9], m[31]);
+	MONT_MUL(w0, w1, w2, u[10], m[30]);
+	MONT_MAC(t0, t1, t2, u[11], m[29]);
+	MONT_MAC(v0, v1, v2, u[12], m[28]);
+	MONT_MAC(w0, w1, w2, u[13], m[27]);
+	MONT_MAC(t0, t1, t2, u[14], m[26]);
+	MONT_MAC(v0, v1, v2, u[15], m[25]);
+	MONT_MAC(w0, w1, w2, u[16], m[24]);
+	MONT_MAC(t0, t1, t2, u[17], m[23]);
+	MONT_MAC(v0, v1, v2, u[18], m[22]);
+	MONT_MAC(w0, w1, w2, u[19], m[21]);
+	MONT_MAC(t0, t1, t2, u[20], m[20]);
+	MONT_MAC(v0, v1, v2, u[21], m[19]);
+	MONT_MAC(w0, w1, w2, u[22], m[18]);
+	MONT_MAC(t0, t1, t2, u[23], m[17]);
+	MONT_MAC(v0, v1, v2, u[24], m[16]);
+	MONT_MAC(w0, w1, w2, u[25], m[15]);
+	MONT_MAC(t0, t1, t2, u[26], m[14]);
+	MONT_MAC(v0, v1, v2, u[27], m[13]);
+	MONT_MAC(w0, w1, w2, u[28], m[12]);
+	MONT_MAC(t0, t1, t2, u[29], m[11]);
+	MONT_MAC(v0, v1, v2, u[30], m[10]);
+	MONT_MAC(w0, w1, w2, u[31], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 41 */
+	MONT_MUL(s0, s1, s2, a[10], a[31]);
+	MONT_MUL(c0, c1, c2, a[11], a[30]);
+	MONT_MAC(s0, s1, s2, a[12], a[29]);
+	MONT_MAC(c0, c1, c2, a[13], a[28]);
+	MONT_MAC(s0, s1, s2, a[14], a[27]);
+	MONT_MAC(c0, c1, c2, a[15], a[26]);
+	MONT_MAC(s0, s1, s2, a[16], a[25]);
+	MONT_MAC(c0, c1, c2, a[17], a[24]);
+	MONT_MAC(s0, s1, s2, a[18], a[23]);
+	MONT_MAC(c0, c1, c2, a[19], a[22]);
+	MONT_MAC(s0, s1, s2, a[20], a[21]);
+	MONT_MAC(t0, t1, t2, u[10], m[31]);
+	MONT_MUL(v0, v1, v2, u[11], m[30]);
+	MONT_MUL(w0, w1, w2, u[12], m[29]);
+	MONT_MAC(t0, t1, t2, u[13], m[28]);
+	MONT_MAC(v0, v1, v2, u[14], m[27]);
+	MONT_MAC(w0, w1, w2, u[15], m[26]);
+	MONT_MAC(t0, t1, t2, u[16], m[25]);
+	MONT_MAC(v0, v1, v2, u[17], m[24]);
+	MONT_MAC(w0, w1, w2, u[18], m[23]);
+	MONT_MAC(t0, t1, t2, u[19], m[22]);
+	MONT_MAC(v0, v1, v2, u[20], m[21]);
+	MONT_MAC(w0, w1, w2, u[21], m[20]);
+	MONT_MAC(t0, t1, t2, u[22], m[19]);
+	MONT_MAC(v0, v1, v2, u[23], m[18]);
+	MONT_MAC(w0, w1, w2, u[24], m[17]);
+	MONT_MAC(t0, t1, t2, u[25], m[16]);
+	MONT_MAC(v0, v1, v2, u[26], m[15]);
+	MONT_MAC(w0, w1, w2, u[27], m[14]);
+	MONT_MAC(t0, t1, t2, u[28], m[13]);
+	MONT_MAC(v0, v1, v2, u[29], m[12]);
+	MONT_MAC(w0, w1, w2, u[30], m[11]);
+	MONT_MAC(t0, t1, t2, u[31], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 42 */
+	MONT_MUL(s0, s1, s2, a[11], a[31]);
+	MONT_MUL(c0, c1, c2, a[12], a[30]);
+	MONT_MAC(s0, s1, s2, a[13], a[29]);
+	MONT_MAC(c0, c1, c2, a[14], a[28]);
+	MONT_MAC(s0, s1, s2, a[15], a[27]);
+	MONT_MAC(c0, c1, c2, a[16], a[26]);
+	MONT_MAC(s0, s1, s2, a[17], a[25]);
+	MONT_MAC(c0, c1, c2, a[18], a[24]);
+	MONT_MAC(s0, s1, s2, a[19], a[23]);
+	MONT_MAC(c0, c1, c2, a[20], a[22]);
+	MONT_MAC(t0, t1, t2, a[21], a[21]);
+	MONT_MUL(v0, v1, v2, u[11], m[31]);
+	MONT_MUL(w0, w1, w2, u[12], m[30]);
+	MONT_MAC(t0, t1, t2, u[13], m[29]);
+	MONT_MAC(v0, v1, v2, u[14], m[28]);
+	MONT_MAC(w0, w1, w2, u[15], m[27]);
+	MONT_MAC(t0, t1, t2, u[16], m[26]);
+	MONT_MAC(v0, v1, v2, u[17], m[25]);
+	MONT_MAC(w0, w1, w2, u[18], m[24]);
+	MONT_MAC(t0, t1, t2, u[19], m[23]);
+	MONT_MAC(v0, v1, v2, u[20], m[22]);
+	MONT_MAC(w0, w1, w2, u[21], m[21]);
+	MONT_MAC(t0, t1, t2, u[22], m[20]);
+	MONT_MAC(v0, v1, v2, u[23], m[19]);
+	MONT_MAC(w0, w1, w2, u[24], m[18]);
+	MONT_MAC(t0, t1, t2, u[25], m[17]);
+	MONT_MAC(v0, v1, v2, u[26], m[16]);
+	MONT_MAC(w0, w1, w2, u[27], m[15]);
+	MONT_MAC(t0, t1, t2, u[28], m[14]);
+	MONT_MAC(v0, v1, v2, u[29], m[13]);
+	MONT_MAC(w0, w1, w2, u[30], m[12]);
+	MONT_MAC(t0, t1, t2, u[31], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 43 */
+	MONT_MUL(s0, s1, s2, a[12], a[31]);
+	MONT_MUL(c0, c1, c2, a[13], a[30]);
+	MONT_MAC(s0, s1, s2, a[14], a[29]);
+	MONT_MAC(c0, c1, c2, a[15], a[28]);
+	MONT_MAC(s0, s1, s2, a[16], a[27]);
+	MONT_MAC(c0, c1, c2, a[17], a[26]);
+	MONT_MAC(s0, s1, s2, a[18], a[25]);
+	MONT_MAC(c0, c1, c2, a[19], a[24]);
+	MONT_MAC(s0, s1, s2, a[20], a[23]);
+	MONT_MAC(c0, c1, c2, a[21], a[22]);
+	MONT_MAC(t0, t1, t2, u[12], m[31]);
+	MONT_MUL(v0, v1, v2, u[13], m[30]);
+	MONT_MUL(w0, w1, w2, u[14], m[29]);
+	MONT_MAC(t0, t1, t2, u[15], m[28]);
+	MONT_MAC(v0, v1, v2, u[16], m[27]);
+	MONT_MAC(w0, w1, w2, u[17], m[26]);
+	MONT_MAC(t0, t1, t2, u[18], m[25]);
+	MONT_MAC(v0, v1, v2, u[19], m[24]);
+	MONT_MAC(w0, w1, w2, u[20], m[23]);
+	MONT_MAC(t0, t1, t2, u[21], m[22]);
+	MONT_MAC(v0, v1, v2, u[22], m[21]);
+	MONT_MAC(w0, w1, w2, u[23], m[20]);
+	MONT_MAC(t0, t1, t2, u[24], m[19]);
+	MONT_MAC(v0, v1, v2, u[25], m[18]);
+	MONT_MAC(w0, w1, w2, u[26], m[17]);
+	MONT_MAC(t0, t1, t2, u[27], m[16]);
+	MONT_MAC(v0, v1, v2, u[28], m[15]);
+	MONT_MAC(w0, w1, w2, u[29], m[14]);
+	MONT_MAC(t0, t1, t2, u[30], m[13]);
+	MONT_MAC(v0, v1, v2, u[31], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 44 */
+	MONT_MUL(s0, s1, s2, a[13], a[31]);
+	MONT_MUL(c0, c1, c2, a[14], a[30]);
+	MONT_MAC(s0, s1, s2, a[15], a[29]);
+	MONT_MAC(c0, c1, c2, a[16], a[28]);
+	MONT_MAC(s0, s1, s2, a[17], a[27]);
+	MONT_MAC(c0, c1, c2, a[18], a[26]);
+	MONT_MAC(s0, s1, s2, a[19], a[25]);
+	MONT_MAC(c0, c1, c2, a[20], a[24]);
+	MONT_MAC(s0, s1, s2, a[21], a[23]);
+	MONT_MAC(t0, t1, t2, a[22], a[22]);
+	MONT_MUL(v0, v1, v2, u[13], m[31]);
+	MONT_MUL(w0, w1, w2, u[14], m[30]);
+	MONT_MAC(t0, t1, t2, u[15], m[29]);
+	MONT_MAC(v0, v1, v2, u[16], m[28]);
+	MONT_MAC(w0, w1, w2, u[17], m[27]);
+	MONT_MAC(t0, t1, t2, u[18], m[26]);
+	MONT_MAC(v0, v1, v2, u[19], m[25]);
+	MONT_MAC(w0, w1, w2, u[20], m[24]);
+	MONT_MAC(t0, t1, t2, u[21], m[23]);
+	MONT_MAC(v0, v1, v2, u[22], m[22]);
+	MONT_MAC(w0, w1, w2, u[23], m[21]);
+	MONT_MAC(t0, t1, t2, u[24], m[20]);
+	MONT_MAC(v0, v1, v2, u[25], m[19]);
+	MONT_MAC(w0, w1, w2, u[26], m[18]);
+	MONT_MAC(t0, t1, t2, u[27], m[17]);
+	MONT_MAC(v0, v1, v2, u[28], m[16]);
+	MONT_MAC(w0, w1, w2, u[29], m[15]);
+	MONT_MAC(t0, t1, t2, u[30], m[14]);
+	MONT_MAC(v0, v1, v2, u[31], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 45 */
+	MONT_MUL(s0, s1, s2, a[14], a[31]);
+	MONT_MUL(c0, c1, c2, a[15], a[30]);
+	MONT_MAC(s0, s1, s2, a[16], a[29]);
+	MONT_MAC(c0, c1, c2, a[17], a[28]);
+	MONT_MAC(s0, s1, s2, a[18], a[27]);
+	MONT_MAC(c0, c1, c2, a[19], a[26]);
+	MONT_MAC(s0, s1, s2, a[20], a[25]);
+	MONT_MAC(c0, c1, c2, a[21], a[24]);
+	MONT_MAC(s0, s1, s2, a[22], a[23]);
+	MONT_MAC(t0, t1, t2, u[14], m[31]);
+	MONT_MUL(v0, v1, v2, u[15], m[30]);
+	MONT_MUL(w0, w1, w2, u[16], m[29]);
+	MONT_MAC(t0, t1, t2, u[17], m[28]);
+	MONT_MAC(v0, v1, v2, u[18], m[27]);
+	MONT_MAC(w0, w1, w2, u[19], m[26]);
+	MONT_MAC(t0, t1, t2, u[20], m[25]);
+	MONT_MAC(v0, v1, v2, u[21], m[24]);
+	MONT_MAC(w0, w1, w2, u[22], m[23]);
+	MONT_MAC(t0, t1, t2, u[23], m[22]);
+	MONT_MAC(v0, v1, v2, u[24], m[21]);
+	MONT_MAC(w0, w1, w2, u[25], m[20]);
+	MONT_MAC(t0, t1, t2, u[26], m[19]);
+	MONT_MAC(v0, v1, v2, u[27], m[18]);
+	MONT_MAC(w0, w1, w2, u[28], m[17]);
+	MONT_MAC(t0, t1, t2, u[29], m[16]);
+	MONT_MAC(v0, v1, v2, u[30], m[15]);
+	MONT_MAC(w0, w1, w2, u[31], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 46 */
+	MONT_MUL(s0, s1, s2, a[15], a[31]);
+	MONT_MUL(c0, c1, c2, a[16], a[30]);
+	MONT_MAC(s0, s1, s2, a[17], a[29]);
+	MONT_MAC(c0, c1, c2, a[18], a[28]);
+	MONT_MAC(s0, s1, s2, a[19], a[27]);
+	MONT_MAC(c0, c1, c2, a[20], a[26]);
+	MONT_MAC(s0, s1, s2, a[21], a[25]);
+	MONT_MAC(c0, c1, c2, a[22], a[24]);
+	MONT_MAC(t0, t1, t2, a[23], a[23]);
+	MONT_MUL(v0, v1, v2, u[15], m[31]);
+	MONT_MUL(w0, w1, w2, u[16], m[30]);
+	MONT_MAC(t0, t1, t2, u[17], m[29]);
+	MONT_MAC(v0, v1, v2, u[18], m[28]);
+	MONT_MAC(w0, w1, w2, u[19], m[27]);
+	MONT_MAC(t0, t1, t2, u[20], m[26]);
+	MONT_MAC(v0, v1, v2, u[21], m[25]);
+	MONT_MAC(w0, w1, w2, u[22], m[24]);
+	MONT_MAC(t0, t1, t2, u[23], m[23]);
+	MONT_MAC(v0, v1, v2, u[24], m[22]);
+	MONT_MAC(w0, w1, w2, u[25], m[21]);
+	MONT_MAC(t0, t1, t2, u[26], m[20]);
+	MONT_MAC(v0, v1, v2, u[27], m[19]);
+	MONT_MAC(w0, w1, w2, u[28], m[18]);
+	MONT_MAC(t0, t1, t2, u[29], m[17]);
+	MONT_MAC(v0, v1, v2, u[30], m[16]);
+	MONT_MAC(w0, w1, w2, u[31], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[14] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 47 */
+	MONT_MUL(s0, s1, s2, a[16], a[31]);
+	MONT_MUL(c0, c1, c2, a[17], a[30]);
+	MONT_MAC(s0, s1, s2, a[18], a[29]);
+	MONT_MAC(c0, c1, c2, a[19], a[28]);
+	MONT_MAC(s0, s1, s2, a[20], a[27]);
+	MONT_MAC(c0, c1, c2, a[21], a[26]);
+	MONT_MAC(s0, s1, s2, a[22], a[25]);
+	MONT_MAC(c0, c1, c2, a[23], a[24]);
+	MONT_MAC(t0, t1, t2, u[16], m[31]);
+	MONT_MUL(v0, v1, v2, u[17], m[30]);
+	MONT_MUL(w0, w1, w2, u[18], m[29]);
+	MONT_MAC(t0, t1, t2, u[19], m[28]);
+	MONT_MAC(v0, v1, v2, u[20], m[27]);
+	MONT_MAC(w0, w1, w2, u[21], m[26]);
+	MONT_MAC(t0, t1, t2, u[22], m[25]);
+	MONT_MAC(v0, v1, v2, u[23], m[24]);
+	MONT_MAC(w0, w1, w2, u[24], m[23]);
+	MONT_MAC(t0, t1, t2, u[25], m[22]);
+	MONT_MAC(v0, v1, v2, u[26], m[21]);
+	MONT_MAC(w0, w1, w2, u[27], m[20]);
+	MONT_MAC(t0, t1, t2, u[28], m[19]);
+	MONT_MAC(v0, v1, v2, u[29], m[18]);
+	MONT_MAC(w0, w1, w2, u[30], m[17]);
+	MONT_MAC(t0, t1, t2, u[31], m[16]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[15] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 48 */
+	MONT_MUL(s0, s1, s2, a[17], a[31]);
+	MONT_MUL(c0, c1, c2, a[18], a[30]);
+	MONT_MAC(s0, s1, s2, a[19], a[29]);
+	MONT_MAC(c0, c1, c2, a[20], a[28]);
+	MONT_MAC(s0, s1, s2, a[21], a[27]);
+	MONT_MAC(c0, c1, c2, a[22], a[26]);
+	MONT_MAC(s0, s1, s2, a[23], a[25]);
+	MONT_MAC(t0, t1, t2, a[24], a[24]);
+	MONT_MUL(v0, v1, v2, u[17], m[31]);
+	MONT_MUL(w0, w1, w2, u[18], m[30]);
+	MONT_MAC(t0, t1, t2, u[19], m[29]);
+	MONT_MAC(v0, v1, v2, u[20], m[28]);
+	MONT_MAC(w0, w1, w2, u[21], m[27]);
+	MONT_MAC(t0, t1, t2, u[22], m[26]);
+	MONT_MAC(v0, v1, v2, u[23], m[25]);
+	MONT_MAC(w0, w1, w2, u[24], m[24]);
+	MONT_MAC(t0, t1, t2, u[25], m[23]);
+	MONT_MAC(v0, v1, v2, u[26], m[22]);
+	MONT_MAC(w0, w1, w2, u[27], m[21]);
+	MONT_MAC(t0, t1, t2, u[28], m[20]);
+	MONT_MAC(v0, v1, v2, u[29], m[19]);
+	MONT_MAC(w0, w1, w2, u[30], m[18]);
+	MONT_MAC(t0, t1, t2, u[31], m[17]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[16] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 49 */
+	MONT_MUL(s0, s1, s2, a[18], a[31]);
+	MONT_MUL(c0, c1, c2, a[19], a[30]);
+	MONT_MAC(s0, s1, s2, a[20], a[29]);
+	MONT_MAC(c0, c1, c2, a[21], a[28]);
+	MONT_MAC(s0, s1, s2, a[22], a[27]);
+	MONT_MAC(c0, c1, c2, a[23], a[26]);
+	MONT_MAC(s0, s1, s2, a[24], a[25]);
+	MONT_MAC(t0, t1, t2, u[18], m[31]);
+	MONT_MUL(v0, v1, v2, u[19], m[30]);
+	MONT_MUL(w0, w1, w2, u[20], m[29]);
+	MONT_MAC(t0, t1, t2, u[21], m[28]);
+	MONT_MAC(v0, v1, v2, u[22], m[27]);
+	MONT_MAC(w0, w1, w2, u[23], m[26]);
+	MONT_MAC(t0, t1, t2, u[24], m[25]);
+	MONT_MAC(v0, v1, v2, u[25], m[24]);
+	MONT_MAC(w0, w1, w2, u[26], m[23]);
+	MONT_MAC(t0, t1, t2, u[27], m[22]);
+	MONT_MAC(v0, v1, v2, u[28], m[21]);
+	MONT_MAC(w0, w1, w2, u[29], m[20]);
+	MONT_MAC(t0, t1, t2, u[30], m[19]);
+	MONT_MAC(v0, v1, v2, u[31], m[18]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[17] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 50 */
+	MONT_MUL(s0, s1, s2, a[19], a[31]);
+	MONT_MUL(c0, c1, c2, a[20], a[30]);
+	MONT_MAC(s0, s1, s2, a[21], a[29]);
+	MONT_MAC(c0, c1, c2, a[22], a[28]);
+	MONT_MAC(s0, s1, s2, a[23], a[27]);
+	MONT_MAC(c0, c1, c2, a[24], a[26]);
+	MONT_MAC(t0, t1, t2, a[25], a[25]);
+	MONT_MUL(v0, v1, v2, u[19], m[31]);
+	MONT_MUL(w0, w1, w2, u[20], m[30]);
+	MONT_MAC(t0, t1, t2, u[21], m[29]);
+	MONT_MAC(v0, v1, v2, u[22], m[28]);
+	MONT_MAC(w0, w1, w2, u[23], m[27]);
+	MONT_MAC(t0, t1, t2, u[24], m[26]);
+	MONT_MAC(v0, v1, v2, u[25], m[25]);
+	MONT_MAC(w0, w1, w2, u[26], m[24]);
+	MONT_MAC(t0, t1, t2, u[27], m[23]);
+	MONT_MAC(v0, v1, v2, u[28], m[22]);
+	MONT_MAC(w0, w1, w2, u[29], m[21]);
+	MONT_MAC(t0, t1, t2, u[30], m[20]);
+	MONT_MAC(v0, v1, v2, u[31], m[19]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[18] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 51 */
+	MONT_MUL(s0, s1, s2, a[20], a[31]);
+	MONT_MUL(c0, c1, c2, a[21], a[30]);
+	MONT_MAC(s0, s1, s2, a[22], a[29]);
+	MONT_MAC(c0, c1, c2, a[23], a[28]);
+	MONT_MAC(s0, s1, s2, a[24], a[27]);
+	MONT_MAC(c0, c1, c2, a[25], a[26]);
+	MONT_MAC(t0, t1, t2, u[20], m[31]);
+	MONT_MUL(v0, v1, v2, u[21], m[30]);
+	MONT_MUL(w0, w1, w2, u[22], m[29]);
+	MONT_MAC(t0, t1, t2, u[23], m[28]);
+	MONT_MAC(v0, v1, v2, u[24], m[27]);
+	MONT_MAC(w0, w1, w2, u[25], m[26]);
+	MONT_MAC(t0, t1, t2, u[26], m[25]);
+	MONT_MAC(v0, v1, v2, u[27], m[24]);
+	MONT_MAC(w0, w1, w2, u[28], m[23]);
+	MONT_MAC(t0, t1, t2, u[29], m[22]);
+	MONT_MAC(v0, v1, v2, u[30], m[21]);
+	MONT_MAC(w0, w1, w2, u[31], m[20]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[19] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 52 */
+	MONT_MUL(s0, s1, s2, a[21], a[31]);
+	MONT_MUL(c0, c1, c2, a[22], a[30]);
+	MONT_MAC(s0, s1, s2, a[23], a[29]);
+	MONT_MAC(c0, c1, c2, a[24], a[28]);
+	MONT_MAC(s0, s1, s2, a[25], a[27]);
+	MONT_MAC(t0, t1, t2, a[26], a[26]);
+	MONT_MUL(v0, v1, v2, u[21], m[31]);
+	MONT_MUL(w0, w1, w2, u[22], m[30]);
+	MONT_MAC(t0, t1, t2, u[23], m[29]);
+	MONT_MAC(v0, v1, v2, u[24], m[28]);
+	MONT_MAC(w0, w1, w2, u[25], m[27]);
+	MONT_MAC(t0, t1, t2, u[26], m[26]);
+	MONT_MAC(v0, v1, v2, u[27], m[25]);
+	MONT_MAC(w0, w1, w2, u[28], m[24]);
+	MONT_MAC(t0, t1, t2, u[29], m[23]);
+	MONT_MAC(v0, v1, v2, u[30], m[22]);
+	MONT_MAC(w0, w1, w2, u[31], m[21]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[20] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 53 */
+	MONT_MUL(s0, s1, s2, a[22], a[31]);
+	MONT_MUL(c0, c1, c2, a[23], a[30]);
+	MONT_MAC(s0, s1, s2, a[24], a[29]);
+	MONT_MAC(c0, c1, c2, a[25], a[28]);
+	MONT_MAC(s0, s1, s2, a[26], a[27]);
+	MONT_MAC(t0, t1, t2, u[22], m[31]);
+	MONT_MUL(v0, v1, v2, u[23], m[30]);
+	MONT_MUL(w0, w1, w2, u[24], m[29]);
+	MONT_MAC(t0, t1, t2, u[25], m[28]);
+	MONT_MAC(v0, v1, v2, u[26], m[27]);
+	MONT_MAC(w0, w1, w2, u[27], m[26]);
+	MONT_MAC(t0, t1, t2, u[28], m[25]);
+	MONT_MAC(v0, v1, v2, u[29], m[24]);
+	MONT_MAC(w0, w1, w2, u[30], m[23]);
+	MONT_MAC(t0, t1, t2, u[31], m[22]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[21] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 54 */
+	MONT_MUL(s0, s1, s2, a[23], a[31]);
+	MONT_MUL(c0, c1, c2, a[24], a[30]);
+	MONT_MAC(s0, s1, s2, a[25], a[29]);
+	MONT_MAC(c0, c1, c2, a[26], a[28]);
+	MONT_MAC(t0, t1, t2, a[27], a[27]);
+	MONT_MUL(v0, v1, v2, u[23], m[31]);
+	MONT_MUL(w0, w1, w2, u[24], m[30]);
+	MONT_MAC(t0, t1, t2, u[25], m[29]);
+	MONT_MAC(v0, v1, v2, u[26], m[28]);
+	MONT_MAC(w0, w1, w2, u[27], m[27]);
+	MONT_MAC(t0, t1, t2, u[28], m[26]);
+	MONT_MAC(v0, v1, v2, u[29], m[25]);
+	MONT_MAC(w0, w1, w2, u[30], m[24]);
+	MONT_MAC(t0, t1, t2, u[31], m[23]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[22] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 55 */
+	MONT_MUL(s0, s1, s2, a[24], a[31]);
+	MONT_MUL(c0, c1, c2, a[25], a[30]);
+	MONT_MAC(s0, s1, s2, a[26], a[29]);
+	MONT_MAC(c0, c1, c2, a[27], a[28]);
+	MONT_MAC(t0, t1, t2, u[24], m[31]);
+	MONT_MUL(v0, v1, v2, u[25], m[30]);
+	MONT_MUL(w0, w1, w2, u[26], m[29]);
+	MONT_MAC(t0, t1, t2, u[27], m[28]);
+	MONT_MAC(v0, v1, v2, u[28], m[27]);
+	MONT_MAC(w0, w1, w2, u[29], m[26]);
+	MONT_MAC(t0, t1, t2, u[30], m[25]);
+	MONT_MAC(v0, v1, v2, u[31], m[24]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[23] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 56 */
+	MONT_MUL(s0, s1, s2, a[25], a[31]);
+	MONT_MUL(c0, c1, c2, a[26], a[30]);
+	MONT_MAC(s0, s1, s2, a[27], a[29]);
+	MONT_MAC(t0, t1, t2, a[28], a[28]);
+	MONT_MUL(v0, v1, v2, u[25], m[31]);
+	MONT_MUL(w0, w1, w2, u[26], m[30]);
+	MONT_MAC(t0, t1, t2, u[27], m[29]);
+	MONT_MAC(v0, v1, v2, u[28], m[28]);
+	MONT_MAC(w0, w1, w2, u[29], m[27]);
+	MONT_MAC(t0, t1, t2, u[30], m[26]);
+	MONT_MAC(v0, v1, v2, u[31], m[25]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[24] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 57 */
+	MONT_MUL(s0, s1, s2, a[26], a[31]);
+	MONT_MUL(c0, c1, c2, a[27], a[30]);
+	MONT_MAC(s0, s1, s2, a[28], a[29]);
+	MONT_MAC(t0, t1, t2, u[26], m[31]);
+	MONT_MUL(v0, v1, v2, u[27], m[30]);
+	MONT_MUL(w0, w1, w2, u[28], m[29]);
+	MONT_MAC(t0, t1, t2, u[29], m[28]);
+	MONT_MAC(v0, v1, v2, u[30], m[27]);
+	MONT_MAC(w0, w1, w2, u[31], m[26]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[25] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 58 */
+	MONT_MUL(s0, s1, s2, a[27], a[31]);
+	MONT_MUL(c0, c1, c2, a[28], a[30]);
+	MONT_MAC(t0, t1, t2, a[29], a[29]);
+	MONT_MUL(v0, v1, v2, u[27], m[31]);
+	MONT_MUL(w0, w1, w2, u[28], m[30]);
+	MONT_MAC(t0, t1, t2, u[29], m[29]);
+	MONT_MAC(v0, v1, v2, u[30], m[28]);
+	MONT_MAC(w0, w1, w2, u[31], m[27]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[26] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 59 */
+	MONT_MUL(s0, s1, s2, a[28], a[31]);
+	MONT_MUL(c0, c1, c2, a[29], a[30]);
+	MONT_MAC(t0, t1, t2, u[28], m[31]);
+	MONT_MUL(v0, v1, v2, u[29], m[30]);
+	MONT_MUL(w0, w1, w2, u[30], m[29]);
+	MONT_MAC(t0, t1, t2, u[31], m[28]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[27] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 60 */
+	MONT_MUL(s0, s1, s2, a[29], a[31]);
+	MONT_MAC(t0, t1, t2, a[30], a[30]);
+	MONT_MUL(v0, v1, v2, u[29], m[31]);
+	MONT_MUL(w0, w1, w2, u[30], m[30]);
+	MONT_MAC(t0, t1, t2, u[31], m[29]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[28] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 61 */
+	MONT_MUL(s0, s1, s2, a[30], a[31]);
+	MONT_MAC(t0, t1, t2, u[30], m[31]);
+	MONT_MUL(v0, v1, v2, u[31], m[30]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[29] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 62 */
+	MONT_MAC(t0, t1, t2, a[31], a[31]);
+	MONT_MUL(v0, v1, v2, u[31], m[31]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	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);
+}
+
+/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */
+static void crypton_mont_sqr48(limb_t *r, const limb_t *a,
+                               const limb_t *m, limb_t n0, limb_t *t)
+{
+	limb_t *u = t, *z = t + 48;
+	limb_t t0 = 0, t1 = 0, t2 = 0, v0, v1, v2, w0, w1, w2, borrow, take;
+	limb_t s0, s1, s2, c0, c1, c2;
+
+	/* column 0 */
+	MONT_MAC(t0, t1, t2, a[0], a[0]);
+	u[0] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[0], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 1 */
+	MONT_MUL(s0, s1, s2, a[0], a[1]);
+	MONT_MAC(t0, t1, t2, u[0], m[1]);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[1] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[1], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 2 */
+	MONT_MUL(s0, s1, s2, a[0], a[2]);
+	MONT_MAC(t0, t1, t2, a[1], a[1]);
+	MONT_MUL(v0, v1, v2, u[0], m[2]);
+	MONT_MUL(w0, w1, w2, u[1], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[2] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[2], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 3 */
+	MONT_MUL(s0, s1, s2, a[0], a[3]);
+	MONT_MUL(c0, c1, c2, a[1], a[2]);
+	MONT_MAC(t0, t1, t2, u[0], m[3]);
+	MONT_MUL(v0, v1, v2, u[1], m[2]);
+	MONT_MUL(w0, w1, w2, u[2], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[3] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[3], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 4 */
+	MONT_MUL(s0, s1, s2, a[0], a[4]);
+	MONT_MUL(c0, c1, c2, a[1], a[3]);
+	MONT_MAC(t0, t1, t2, a[2], a[2]);
+	MONT_MUL(v0, v1, v2, u[0], m[4]);
+	MONT_MUL(w0, w1, w2, u[1], m[3]);
+	MONT_MAC(t0, t1, t2, u[2], m[2]);
+	MONT_MAC(v0, v1, v2, u[3], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[4] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[4], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 5 */
+	MONT_MUL(s0, s1, s2, a[0], a[5]);
+	MONT_MUL(c0, c1, c2, a[1], a[4]);
+	MONT_MAC(s0, s1, s2, a[2], a[3]);
+	MONT_MAC(t0, t1, t2, u[0], m[5]);
+	MONT_MUL(v0, v1, v2, u[1], m[4]);
+	MONT_MUL(w0, w1, w2, u[2], m[3]);
+	MONT_MAC(t0, t1, t2, u[3], m[2]);
+	MONT_MAC(v0, v1, v2, u[4], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[5] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[5], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 6 */
+	MONT_MUL(s0, s1, s2, a[0], a[6]);
+	MONT_MUL(c0, c1, c2, a[1], a[5]);
+	MONT_MAC(s0, s1, s2, a[2], a[4]);
+	MONT_MAC(t0, t1, t2, a[3], a[3]);
+	MONT_MUL(v0, v1, v2, u[0], m[6]);
+	MONT_MUL(w0, w1, w2, u[1], m[5]);
+	MONT_MAC(t0, t1, t2, u[2], m[4]);
+	MONT_MAC(v0, v1, v2, u[3], m[3]);
+	MONT_MAC(w0, w1, w2, u[4], m[2]);
+	MONT_MAC(t0, t1, t2, u[5], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[6] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[6], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 7 */
+	MONT_MUL(s0, s1, s2, a[0], a[7]);
+	MONT_MUL(c0, c1, c2, a[1], a[6]);
+	MONT_MAC(s0, s1, s2, a[2], a[5]);
+	MONT_MAC(c0, c1, c2, a[3], a[4]);
+	MONT_MAC(t0, t1, t2, u[0], m[7]);
+	MONT_MUL(v0, v1, v2, u[1], m[6]);
+	MONT_MUL(w0, w1, w2, u[2], m[5]);
+	MONT_MAC(t0, t1, t2, u[3], m[4]);
+	MONT_MAC(v0, v1, v2, u[4], m[3]);
+	MONT_MAC(w0, w1, w2, u[5], m[2]);
+	MONT_MAC(t0, t1, t2, u[6], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[7] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[7], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 8 */
+	MONT_MUL(s0, s1, s2, a[0], a[8]);
+	MONT_MUL(c0, c1, c2, a[1], a[7]);
+	MONT_MAC(s0, s1, s2, a[2], a[6]);
+	MONT_MAC(c0, c1, c2, a[3], a[5]);
+	MONT_MAC(t0, t1, t2, a[4], a[4]);
+	MONT_MUL(v0, v1, v2, u[0], m[8]);
+	MONT_MUL(w0, w1, w2, u[1], m[7]);
+	MONT_MAC(t0, t1, t2, u[2], m[6]);
+	MONT_MAC(v0, v1, v2, u[3], m[5]);
+	MONT_MAC(w0, w1, w2, u[4], m[4]);
+	MONT_MAC(t0, t1, t2, u[5], m[3]);
+	MONT_MAC(v0, v1, v2, u[6], m[2]);
+	MONT_MAC(w0, w1, w2, u[7], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[8] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[8], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 9 */
+	MONT_MUL(s0, s1, s2, a[0], a[9]);
+	MONT_MUL(c0, c1, c2, a[1], a[8]);
+	MONT_MAC(s0, s1, s2, a[2], a[7]);
+	MONT_MAC(c0, c1, c2, a[3], a[6]);
+	MONT_MAC(s0, s1, s2, a[4], a[5]);
+	MONT_MAC(t0, t1, t2, u[0], m[9]);
+	MONT_MUL(v0, v1, v2, u[1], m[8]);
+	MONT_MUL(w0, w1, w2, u[2], m[7]);
+	MONT_MAC(t0, t1, t2, u[3], m[6]);
+	MONT_MAC(v0, v1, v2, u[4], m[5]);
+	MONT_MAC(w0, w1, w2, u[5], m[4]);
+	MONT_MAC(t0, t1, t2, u[6], m[3]);
+	MONT_MAC(v0, v1, v2, u[7], m[2]);
+	MONT_MAC(w0, w1, w2, u[8], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[9] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[9], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 10 */
+	MONT_MUL(s0, s1, s2, a[0], a[10]);
+	MONT_MUL(c0, c1, c2, a[1], a[9]);
+	MONT_MAC(s0, s1, s2, a[2], a[8]);
+	MONT_MAC(c0, c1, c2, a[3], a[7]);
+	MONT_MAC(s0, s1, s2, a[4], a[6]);
+	MONT_MAC(t0, t1, t2, a[5], a[5]);
+	MONT_MUL(v0, v1, v2, u[0], m[10]);
+	MONT_MUL(w0, w1, w2, u[1], m[9]);
+	MONT_MAC(t0, t1, t2, u[2], m[8]);
+	MONT_MAC(v0, v1, v2, u[3], m[7]);
+	MONT_MAC(w0, w1, w2, u[4], m[6]);
+	MONT_MAC(t0, t1, t2, u[5], m[5]);
+	MONT_MAC(v0, v1, v2, u[6], m[4]);
+	MONT_MAC(w0, w1, w2, u[7], m[3]);
+	MONT_MAC(t0, t1, t2, u[8], m[2]);
+	MONT_MAC(v0, v1, v2, u[9], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[10] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[10], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 11 */
+	MONT_MUL(s0, s1, s2, a[0], a[11]);
+	MONT_MUL(c0, c1, c2, a[1], a[10]);
+	MONT_MAC(s0, s1, s2, a[2], a[9]);
+	MONT_MAC(c0, c1, c2, a[3], a[8]);
+	MONT_MAC(s0, s1, s2, a[4], a[7]);
+	MONT_MAC(c0, c1, c2, a[5], a[6]);
+	MONT_MAC(t0, t1, t2, u[0], m[11]);
+	MONT_MUL(v0, v1, v2, u[1], m[10]);
+	MONT_MUL(w0, w1, w2, u[2], m[9]);
+	MONT_MAC(t0, t1, t2, u[3], m[8]);
+	MONT_MAC(v0, v1, v2, u[4], m[7]);
+	MONT_MAC(w0, w1, w2, u[5], m[6]);
+	MONT_MAC(t0, t1, t2, u[6], m[5]);
+	MONT_MAC(v0, v1, v2, u[7], m[4]);
+	MONT_MAC(w0, w1, w2, u[8], m[3]);
+	MONT_MAC(t0, t1, t2, u[9], m[2]);
+	MONT_MAC(v0, v1, v2, u[10], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[11] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[11], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 12 */
+	MONT_MUL(s0, s1, s2, a[0], a[12]);
+	MONT_MUL(c0, c1, c2, a[1], a[11]);
+	MONT_MAC(s0, s1, s2, a[2], a[10]);
+	MONT_MAC(c0, c1, c2, a[3], a[9]);
+	MONT_MAC(s0, s1, s2, a[4], a[8]);
+	MONT_MAC(c0, c1, c2, a[5], a[7]);
+	MONT_MAC(t0, t1, t2, a[6], a[6]);
+	MONT_MUL(v0, v1, v2, u[0], m[12]);
+	MONT_MUL(w0, w1, w2, u[1], m[11]);
+	MONT_MAC(t0, t1, t2, u[2], m[10]);
+	MONT_MAC(v0, v1, v2, u[3], m[9]);
+	MONT_MAC(w0, w1, w2, u[4], m[8]);
+	MONT_MAC(t0, t1, t2, u[5], m[7]);
+	MONT_MAC(v0, v1, v2, u[6], m[6]);
+	MONT_MAC(w0, w1, w2, u[7], m[5]);
+	MONT_MAC(t0, t1, t2, u[8], m[4]);
+	MONT_MAC(v0, v1, v2, u[9], m[3]);
+	MONT_MAC(w0, w1, w2, u[10], m[2]);
+	MONT_MAC(t0, t1, t2, u[11], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[12] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[12], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 13 */
+	MONT_MUL(s0, s1, s2, a[0], a[13]);
+	MONT_MUL(c0, c1, c2, a[1], a[12]);
+	MONT_MAC(s0, s1, s2, a[2], a[11]);
+	MONT_MAC(c0, c1, c2, a[3], a[10]);
+	MONT_MAC(s0, s1, s2, a[4], a[9]);
+	MONT_MAC(c0, c1, c2, a[5], a[8]);
+	MONT_MAC(s0, s1, s2, a[6], a[7]);
+	MONT_MAC(t0, t1, t2, u[0], m[13]);
+	MONT_MUL(v0, v1, v2, u[1], m[12]);
+	MONT_MUL(w0, w1, w2, u[2], m[11]);
+	MONT_MAC(t0, t1, t2, u[3], m[10]);
+	MONT_MAC(v0, v1, v2, u[4], m[9]);
+	MONT_MAC(w0, w1, w2, u[5], m[8]);
+	MONT_MAC(t0, t1, t2, u[6], m[7]);
+	MONT_MAC(v0, v1, v2, u[7], m[6]);
+	MONT_MAC(w0, w1, w2, u[8], m[5]);
+	MONT_MAC(t0, t1, t2, u[9], m[4]);
+	MONT_MAC(v0, v1, v2, u[10], m[3]);
+	MONT_MAC(w0, w1, w2, u[11], m[2]);
+	MONT_MAC(t0, t1, t2, u[12], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[13] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[13], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 14 */
+	MONT_MUL(s0, s1, s2, a[0], a[14]);
+	MONT_MUL(c0, c1, c2, a[1], a[13]);
+	MONT_MAC(s0, s1, s2, a[2], a[12]);
+	MONT_MAC(c0, c1, c2, a[3], a[11]);
+	MONT_MAC(s0, s1, s2, a[4], a[10]);
+	MONT_MAC(c0, c1, c2, a[5], a[9]);
+	MONT_MAC(s0, s1, s2, a[6], a[8]);
+	MONT_MAC(t0, t1, t2, a[7], a[7]);
+	MONT_MUL(v0, v1, v2, u[0], m[14]);
+	MONT_MUL(w0, w1, w2, u[1], m[13]);
+	MONT_MAC(t0, t1, t2, u[2], m[12]);
+	MONT_MAC(v0, v1, v2, u[3], m[11]);
+	MONT_MAC(w0, w1, w2, u[4], m[10]);
+	MONT_MAC(t0, t1, t2, u[5], m[9]);
+	MONT_MAC(v0, v1, v2, u[6], m[8]);
+	MONT_MAC(w0, w1, w2, u[7], m[7]);
+	MONT_MAC(t0, t1, t2, u[8], m[6]);
+	MONT_MAC(v0, v1, v2, u[9], m[5]);
+	MONT_MAC(w0, w1, w2, u[10], m[4]);
+	MONT_MAC(t0, t1, t2, u[11], m[3]);
+	MONT_MAC(v0, v1, v2, u[12], m[2]);
+	MONT_MAC(w0, w1, w2, u[13], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[14] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[14], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 15 */
+	MONT_MUL(s0, s1, s2, a[0], a[15]);
+	MONT_MUL(c0, c1, c2, a[1], a[14]);
+	MONT_MAC(s0, s1, s2, a[2], a[13]);
+	MONT_MAC(c0, c1, c2, a[3], a[12]);
+	MONT_MAC(s0, s1, s2, a[4], a[11]);
+	MONT_MAC(c0, c1, c2, a[5], a[10]);
+	MONT_MAC(s0, s1, s2, a[6], a[9]);
+	MONT_MAC(c0, c1, c2, a[7], a[8]);
+	MONT_MAC(t0, t1, t2, u[0], m[15]);
+	MONT_MUL(v0, v1, v2, u[1], m[14]);
+	MONT_MUL(w0, w1, w2, u[2], m[13]);
+	MONT_MAC(t0, t1, t2, u[3], m[12]);
+	MONT_MAC(v0, v1, v2, u[4], m[11]);
+	MONT_MAC(w0, w1, w2, u[5], m[10]);
+	MONT_MAC(t0, t1, t2, u[6], m[9]);
+	MONT_MAC(v0, v1, v2, u[7], m[8]);
+	MONT_MAC(w0, w1, w2, u[8], m[7]);
+	MONT_MAC(t0, t1, t2, u[9], m[6]);
+	MONT_MAC(v0, v1, v2, u[10], m[5]);
+	MONT_MAC(w0, w1, w2, u[11], m[4]);
+	MONT_MAC(t0, t1, t2, u[12], m[3]);
+	MONT_MAC(v0, v1, v2, u[13], m[2]);
+	MONT_MAC(w0, w1, w2, u[14], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[15] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[15], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 16 */
+	MONT_MUL(s0, s1, s2, a[0], a[16]);
+	MONT_MUL(c0, c1, c2, a[1], a[15]);
+	MONT_MAC(s0, s1, s2, a[2], a[14]);
+	MONT_MAC(c0, c1, c2, a[3], a[13]);
+	MONT_MAC(s0, s1, s2, a[4], a[12]);
+	MONT_MAC(c0, c1, c2, a[5], a[11]);
+	MONT_MAC(s0, s1, s2, a[6], a[10]);
+	MONT_MAC(c0, c1, c2, a[7], a[9]);
+	MONT_MAC(t0, t1, t2, a[8], a[8]);
+	MONT_MUL(v0, v1, v2, u[0], m[16]);
+	MONT_MUL(w0, w1, w2, u[1], m[15]);
+	MONT_MAC(t0, t1, t2, u[2], m[14]);
+	MONT_MAC(v0, v1, v2, u[3], m[13]);
+	MONT_MAC(w0, w1, w2, u[4], m[12]);
+	MONT_MAC(t0, t1, t2, u[5], m[11]);
+	MONT_MAC(v0, v1, v2, u[6], m[10]);
+	MONT_MAC(w0, w1, w2, u[7], m[9]);
+	MONT_MAC(t0, t1, t2, u[8], m[8]);
+	MONT_MAC(v0, v1, v2, u[9], m[7]);
+	MONT_MAC(w0, w1, w2, u[10], m[6]);
+	MONT_MAC(t0, t1, t2, u[11], m[5]);
+	MONT_MAC(v0, v1, v2, u[12], m[4]);
+	MONT_MAC(w0, w1, w2, u[13], m[3]);
+	MONT_MAC(t0, t1, t2, u[14], m[2]);
+	MONT_MAC(v0, v1, v2, u[15], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[16] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[16], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 17 */
+	MONT_MUL(s0, s1, s2, a[0], a[17]);
+	MONT_MUL(c0, c1, c2, a[1], a[16]);
+	MONT_MAC(s0, s1, s2, a[2], a[15]);
+	MONT_MAC(c0, c1, c2, a[3], a[14]);
+	MONT_MAC(s0, s1, s2, a[4], a[13]);
+	MONT_MAC(c0, c1, c2, a[5], a[12]);
+	MONT_MAC(s0, s1, s2, a[6], a[11]);
+	MONT_MAC(c0, c1, c2, a[7], a[10]);
+	MONT_MAC(s0, s1, s2, a[8], a[9]);
+	MONT_MAC(t0, t1, t2, u[0], m[17]);
+	MONT_MUL(v0, v1, v2, u[1], m[16]);
+	MONT_MUL(w0, w1, w2, u[2], m[15]);
+	MONT_MAC(t0, t1, t2, u[3], m[14]);
+	MONT_MAC(v0, v1, v2, u[4], m[13]);
+	MONT_MAC(w0, w1, w2, u[5], m[12]);
+	MONT_MAC(t0, t1, t2, u[6], m[11]);
+	MONT_MAC(v0, v1, v2, u[7], m[10]);
+	MONT_MAC(w0, w1, w2, u[8], m[9]);
+	MONT_MAC(t0, t1, t2, u[9], m[8]);
+	MONT_MAC(v0, v1, v2, u[10], m[7]);
+	MONT_MAC(w0, w1, w2, u[11], m[6]);
+	MONT_MAC(t0, t1, t2, u[12], m[5]);
+	MONT_MAC(v0, v1, v2, u[13], m[4]);
+	MONT_MAC(w0, w1, w2, u[14], m[3]);
+	MONT_MAC(t0, t1, t2, u[15], m[2]);
+	MONT_MAC(v0, v1, v2, u[16], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[17] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[17], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 18 */
+	MONT_MUL(s0, s1, s2, a[0], a[18]);
+	MONT_MUL(c0, c1, c2, a[1], a[17]);
+	MONT_MAC(s0, s1, s2, a[2], a[16]);
+	MONT_MAC(c0, c1, c2, a[3], a[15]);
+	MONT_MAC(s0, s1, s2, a[4], a[14]);
+	MONT_MAC(c0, c1, c2, a[5], a[13]);
+	MONT_MAC(s0, s1, s2, a[6], a[12]);
+	MONT_MAC(c0, c1, c2, a[7], a[11]);
+	MONT_MAC(s0, s1, s2, a[8], a[10]);
+	MONT_MAC(t0, t1, t2, a[9], a[9]);
+	MONT_MUL(v0, v1, v2, u[0], m[18]);
+	MONT_MUL(w0, w1, w2, u[1], m[17]);
+	MONT_MAC(t0, t1, t2, u[2], m[16]);
+	MONT_MAC(v0, v1, v2, u[3], m[15]);
+	MONT_MAC(w0, w1, w2, u[4], m[14]);
+	MONT_MAC(t0, t1, t2, u[5], m[13]);
+	MONT_MAC(v0, v1, v2, u[6], m[12]);
+	MONT_MAC(w0, w1, w2, u[7], m[11]);
+	MONT_MAC(t0, t1, t2, u[8], m[10]);
+	MONT_MAC(v0, v1, v2, u[9], m[9]);
+	MONT_MAC(w0, w1, w2, u[10], m[8]);
+	MONT_MAC(t0, t1, t2, u[11], m[7]);
+	MONT_MAC(v0, v1, v2, u[12], m[6]);
+	MONT_MAC(w0, w1, w2, u[13], m[5]);
+	MONT_MAC(t0, t1, t2, u[14], m[4]);
+	MONT_MAC(v0, v1, v2, u[15], m[3]);
+	MONT_MAC(w0, w1, w2, u[16], m[2]);
+	MONT_MAC(t0, t1, t2, u[17], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[18] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[18], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 19 */
+	MONT_MUL(s0, s1, s2, a[0], a[19]);
+	MONT_MUL(c0, c1, c2, a[1], a[18]);
+	MONT_MAC(s0, s1, s2, a[2], a[17]);
+	MONT_MAC(c0, c1, c2, a[3], a[16]);
+	MONT_MAC(s0, s1, s2, a[4], a[15]);
+	MONT_MAC(c0, c1, c2, a[5], a[14]);
+	MONT_MAC(s0, s1, s2, a[6], a[13]);
+	MONT_MAC(c0, c1, c2, a[7], a[12]);
+	MONT_MAC(s0, s1, s2, a[8], a[11]);
+	MONT_MAC(c0, c1, c2, a[9], a[10]);
+	MONT_MAC(t0, t1, t2, u[0], m[19]);
+	MONT_MUL(v0, v1, v2, u[1], m[18]);
+	MONT_MUL(w0, w1, w2, u[2], m[17]);
+	MONT_MAC(t0, t1, t2, u[3], m[16]);
+	MONT_MAC(v0, v1, v2, u[4], m[15]);
+	MONT_MAC(w0, w1, w2, u[5], m[14]);
+	MONT_MAC(t0, t1, t2, u[6], m[13]);
+	MONT_MAC(v0, v1, v2, u[7], m[12]);
+	MONT_MAC(w0, w1, w2, u[8], m[11]);
+	MONT_MAC(t0, t1, t2, u[9], m[10]);
+	MONT_MAC(v0, v1, v2, u[10], m[9]);
+	MONT_MAC(w0, w1, w2, u[11], m[8]);
+	MONT_MAC(t0, t1, t2, u[12], m[7]);
+	MONT_MAC(v0, v1, v2, u[13], m[6]);
+	MONT_MAC(w0, w1, w2, u[14], m[5]);
+	MONT_MAC(t0, t1, t2, u[15], m[4]);
+	MONT_MAC(v0, v1, v2, u[16], m[3]);
+	MONT_MAC(w0, w1, w2, u[17], m[2]);
+	MONT_MAC(t0, t1, t2, u[18], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[19] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[19], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 20 */
+	MONT_MUL(s0, s1, s2, a[0], a[20]);
+	MONT_MUL(c0, c1, c2, a[1], a[19]);
+	MONT_MAC(s0, s1, s2, a[2], a[18]);
+	MONT_MAC(c0, c1, c2, a[3], a[17]);
+	MONT_MAC(s0, s1, s2, a[4], a[16]);
+	MONT_MAC(c0, c1, c2, a[5], a[15]);
+	MONT_MAC(s0, s1, s2, a[6], a[14]);
+	MONT_MAC(c0, c1, c2, a[7], a[13]);
+	MONT_MAC(s0, s1, s2, a[8], a[12]);
+	MONT_MAC(c0, c1, c2, a[9], a[11]);
+	MONT_MAC(t0, t1, t2, a[10], a[10]);
+	MONT_MUL(v0, v1, v2, u[0], m[20]);
+	MONT_MUL(w0, w1, w2, u[1], m[19]);
+	MONT_MAC(t0, t1, t2, u[2], m[18]);
+	MONT_MAC(v0, v1, v2, u[3], m[17]);
+	MONT_MAC(w0, w1, w2, u[4], m[16]);
+	MONT_MAC(t0, t1, t2, u[5], m[15]);
+	MONT_MAC(v0, v1, v2, u[6], m[14]);
+	MONT_MAC(w0, w1, w2, u[7], m[13]);
+	MONT_MAC(t0, t1, t2, u[8], m[12]);
+	MONT_MAC(v0, v1, v2, u[9], m[11]);
+	MONT_MAC(w0, w1, w2, u[10], m[10]);
+	MONT_MAC(t0, t1, t2, u[11], m[9]);
+	MONT_MAC(v0, v1, v2, u[12], m[8]);
+	MONT_MAC(w0, w1, w2, u[13], m[7]);
+	MONT_MAC(t0, t1, t2, u[14], m[6]);
+	MONT_MAC(v0, v1, v2, u[15], m[5]);
+	MONT_MAC(w0, w1, w2, u[16], m[4]);
+	MONT_MAC(t0, t1, t2, u[17], m[3]);
+	MONT_MAC(v0, v1, v2, u[18], m[2]);
+	MONT_MAC(w0, w1, w2, u[19], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[20] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[20], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 21 */
+	MONT_MUL(s0, s1, s2, a[0], a[21]);
+	MONT_MUL(c0, c1, c2, a[1], a[20]);
+	MONT_MAC(s0, s1, s2, a[2], a[19]);
+	MONT_MAC(c0, c1, c2, a[3], a[18]);
+	MONT_MAC(s0, s1, s2, a[4], a[17]);
+	MONT_MAC(c0, c1, c2, a[5], a[16]);
+	MONT_MAC(s0, s1, s2, a[6], a[15]);
+	MONT_MAC(c0, c1, c2, a[7], a[14]);
+	MONT_MAC(s0, s1, s2, a[8], a[13]);
+	MONT_MAC(c0, c1, c2, a[9], a[12]);
+	MONT_MAC(s0, s1, s2, a[10], a[11]);
+	MONT_MAC(t0, t1, t2, u[0], m[21]);
+	MONT_MUL(v0, v1, v2, u[1], m[20]);
+	MONT_MUL(w0, w1, w2, u[2], m[19]);
+	MONT_MAC(t0, t1, t2, u[3], m[18]);
+	MONT_MAC(v0, v1, v2, u[4], m[17]);
+	MONT_MAC(w0, w1, w2, u[5], m[16]);
+	MONT_MAC(t0, t1, t2, u[6], m[15]);
+	MONT_MAC(v0, v1, v2, u[7], m[14]);
+	MONT_MAC(w0, w1, w2, u[8], m[13]);
+	MONT_MAC(t0, t1, t2, u[9], m[12]);
+	MONT_MAC(v0, v1, v2, u[10], m[11]);
+	MONT_MAC(w0, w1, w2, u[11], m[10]);
+	MONT_MAC(t0, t1, t2, u[12], m[9]);
+	MONT_MAC(v0, v1, v2, u[13], m[8]);
+	MONT_MAC(w0, w1, w2, u[14], m[7]);
+	MONT_MAC(t0, t1, t2, u[15], m[6]);
+	MONT_MAC(v0, v1, v2, u[16], m[5]);
+	MONT_MAC(w0, w1, w2, u[17], m[4]);
+	MONT_MAC(t0, t1, t2, u[18], m[3]);
+	MONT_MAC(v0, v1, v2, u[19], m[2]);
+	MONT_MAC(w0, w1, w2, u[20], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[21] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[21], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 22 */
+	MONT_MUL(s0, s1, s2, a[0], a[22]);
+	MONT_MUL(c0, c1, c2, a[1], a[21]);
+	MONT_MAC(s0, s1, s2, a[2], a[20]);
+	MONT_MAC(c0, c1, c2, a[3], a[19]);
+	MONT_MAC(s0, s1, s2, a[4], a[18]);
+	MONT_MAC(c0, c1, c2, a[5], a[17]);
+	MONT_MAC(s0, s1, s2, a[6], a[16]);
+	MONT_MAC(c0, c1, c2, a[7], a[15]);
+	MONT_MAC(s0, s1, s2, a[8], a[14]);
+	MONT_MAC(c0, c1, c2, a[9], a[13]);
+	MONT_MAC(s0, s1, s2, a[10], a[12]);
+	MONT_MAC(t0, t1, t2, a[11], a[11]);
+	MONT_MUL(v0, v1, v2, u[0], m[22]);
+	MONT_MUL(w0, w1, w2, u[1], m[21]);
+	MONT_MAC(t0, t1, t2, u[2], m[20]);
+	MONT_MAC(v0, v1, v2, u[3], m[19]);
+	MONT_MAC(w0, w1, w2, u[4], m[18]);
+	MONT_MAC(t0, t1, t2, u[5], m[17]);
+	MONT_MAC(v0, v1, v2, u[6], m[16]);
+	MONT_MAC(w0, w1, w2, u[7], m[15]);
+	MONT_MAC(t0, t1, t2, u[8], m[14]);
+	MONT_MAC(v0, v1, v2, u[9], m[13]);
+	MONT_MAC(w0, w1, w2, u[10], m[12]);
+	MONT_MAC(t0, t1, t2, u[11], m[11]);
+	MONT_MAC(v0, v1, v2, u[12], m[10]);
+	MONT_MAC(w0, w1, w2, u[13], m[9]);
+	MONT_MAC(t0, t1, t2, u[14], m[8]);
+	MONT_MAC(v0, v1, v2, u[15], m[7]);
+	MONT_MAC(w0, w1, w2, u[16], m[6]);
+	MONT_MAC(t0, t1, t2, u[17], m[5]);
+	MONT_MAC(v0, v1, v2, u[18], m[4]);
+	MONT_MAC(w0, w1, w2, u[19], m[3]);
+	MONT_MAC(t0, t1, t2, u[20], m[2]);
+	MONT_MAC(v0, v1, v2, u[21], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[22] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[22], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 23 */
+	MONT_MUL(s0, s1, s2, a[0], a[23]);
+	MONT_MUL(c0, c1, c2, a[1], a[22]);
+	MONT_MAC(s0, s1, s2, a[2], a[21]);
+	MONT_MAC(c0, c1, c2, a[3], a[20]);
+	MONT_MAC(s0, s1, s2, a[4], a[19]);
+	MONT_MAC(c0, c1, c2, a[5], a[18]);
+	MONT_MAC(s0, s1, s2, a[6], a[17]);
+	MONT_MAC(c0, c1, c2, a[7], a[16]);
+	MONT_MAC(s0, s1, s2, a[8], a[15]);
+	MONT_MAC(c0, c1, c2, a[9], a[14]);
+	MONT_MAC(s0, s1, s2, a[10], a[13]);
+	MONT_MAC(c0, c1, c2, a[11], a[12]);
+	MONT_MAC(t0, t1, t2, u[0], m[23]);
+	MONT_MUL(v0, v1, v2, u[1], m[22]);
+	MONT_MUL(w0, w1, w2, u[2], m[21]);
+	MONT_MAC(t0, t1, t2, u[3], m[20]);
+	MONT_MAC(v0, v1, v2, u[4], m[19]);
+	MONT_MAC(w0, w1, w2, u[5], m[18]);
+	MONT_MAC(t0, t1, t2, u[6], m[17]);
+	MONT_MAC(v0, v1, v2, u[7], m[16]);
+	MONT_MAC(w0, w1, w2, u[8], m[15]);
+	MONT_MAC(t0, t1, t2, u[9], m[14]);
+	MONT_MAC(v0, v1, v2, u[10], m[13]);
+	MONT_MAC(w0, w1, w2, u[11], m[12]);
+	MONT_MAC(t0, t1, t2, u[12], m[11]);
+	MONT_MAC(v0, v1, v2, u[13], m[10]);
+	MONT_MAC(w0, w1, w2, u[14], m[9]);
+	MONT_MAC(t0, t1, t2, u[15], m[8]);
+	MONT_MAC(v0, v1, v2, u[16], m[7]);
+	MONT_MAC(w0, w1, w2, u[17], m[6]);
+	MONT_MAC(t0, t1, t2, u[18], m[5]);
+	MONT_MAC(v0, v1, v2, u[19], m[4]);
+	MONT_MAC(w0, w1, w2, u[20], m[3]);
+	MONT_MAC(t0, t1, t2, u[21], m[2]);
+	MONT_MAC(v0, v1, v2, u[22], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[23] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[23], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 24 */
+	MONT_MUL(s0, s1, s2, a[0], a[24]);
+	MONT_MUL(c0, c1, c2, a[1], a[23]);
+	MONT_MAC(s0, s1, s2, a[2], a[22]);
+	MONT_MAC(c0, c1, c2, a[3], a[21]);
+	MONT_MAC(s0, s1, s2, a[4], a[20]);
+	MONT_MAC(c0, c1, c2, a[5], a[19]);
+	MONT_MAC(s0, s1, s2, a[6], a[18]);
+	MONT_MAC(c0, c1, c2, a[7], a[17]);
+	MONT_MAC(s0, s1, s2, a[8], a[16]);
+	MONT_MAC(c0, c1, c2, a[9], a[15]);
+	MONT_MAC(s0, s1, s2, a[10], a[14]);
+	MONT_MAC(c0, c1, c2, a[11], a[13]);
+	MONT_MAC(t0, t1, t2, a[12], a[12]);
+	MONT_MUL(v0, v1, v2, u[0], m[24]);
+	MONT_MUL(w0, w1, w2, u[1], m[23]);
+	MONT_MAC(t0, t1, t2, u[2], m[22]);
+	MONT_MAC(v0, v1, v2, u[3], m[21]);
+	MONT_MAC(w0, w1, w2, u[4], m[20]);
+	MONT_MAC(t0, t1, t2, u[5], m[19]);
+	MONT_MAC(v0, v1, v2, u[6], m[18]);
+	MONT_MAC(w0, w1, w2, u[7], m[17]);
+	MONT_MAC(t0, t1, t2, u[8], m[16]);
+	MONT_MAC(v0, v1, v2, u[9], m[15]);
+	MONT_MAC(w0, w1, w2, u[10], m[14]);
+	MONT_MAC(t0, t1, t2, u[11], m[13]);
+	MONT_MAC(v0, v1, v2, u[12], m[12]);
+	MONT_MAC(w0, w1, w2, u[13], m[11]);
+	MONT_MAC(t0, t1, t2, u[14], m[10]);
+	MONT_MAC(v0, v1, v2, u[15], m[9]);
+	MONT_MAC(w0, w1, w2, u[16], m[8]);
+	MONT_MAC(t0, t1, t2, u[17], m[7]);
+	MONT_MAC(v0, v1, v2, u[18], m[6]);
+	MONT_MAC(w0, w1, w2, u[19], m[5]);
+	MONT_MAC(t0, t1, t2, u[20], m[4]);
+	MONT_MAC(v0, v1, v2, u[21], m[3]);
+	MONT_MAC(w0, w1, w2, u[22], m[2]);
+	MONT_MAC(t0, t1, t2, u[23], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[24] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[24], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 25 */
+	MONT_MUL(s0, s1, s2, a[0], a[25]);
+	MONT_MUL(c0, c1, c2, a[1], a[24]);
+	MONT_MAC(s0, s1, s2, a[2], a[23]);
+	MONT_MAC(c0, c1, c2, a[3], a[22]);
+	MONT_MAC(s0, s1, s2, a[4], a[21]);
+	MONT_MAC(c0, c1, c2, a[5], a[20]);
+	MONT_MAC(s0, s1, s2, a[6], a[19]);
+	MONT_MAC(c0, c1, c2, a[7], a[18]);
+	MONT_MAC(s0, s1, s2, a[8], a[17]);
+	MONT_MAC(c0, c1, c2, a[9], a[16]);
+	MONT_MAC(s0, s1, s2, a[10], a[15]);
+	MONT_MAC(c0, c1, c2, a[11], a[14]);
+	MONT_MAC(s0, s1, s2, a[12], a[13]);
+	MONT_MAC(t0, t1, t2, u[0], m[25]);
+	MONT_MUL(v0, v1, v2, u[1], m[24]);
+	MONT_MUL(w0, w1, w2, u[2], m[23]);
+	MONT_MAC(t0, t1, t2, u[3], m[22]);
+	MONT_MAC(v0, v1, v2, u[4], m[21]);
+	MONT_MAC(w0, w1, w2, u[5], m[20]);
+	MONT_MAC(t0, t1, t2, u[6], m[19]);
+	MONT_MAC(v0, v1, v2, u[7], m[18]);
+	MONT_MAC(w0, w1, w2, u[8], m[17]);
+	MONT_MAC(t0, t1, t2, u[9], m[16]);
+	MONT_MAC(v0, v1, v2, u[10], m[15]);
+	MONT_MAC(w0, w1, w2, u[11], m[14]);
+	MONT_MAC(t0, t1, t2, u[12], m[13]);
+	MONT_MAC(v0, v1, v2, u[13], m[12]);
+	MONT_MAC(w0, w1, w2, u[14], m[11]);
+	MONT_MAC(t0, t1, t2, u[15], m[10]);
+	MONT_MAC(v0, v1, v2, u[16], m[9]);
+	MONT_MAC(w0, w1, w2, u[17], m[8]);
+	MONT_MAC(t0, t1, t2, u[18], m[7]);
+	MONT_MAC(v0, v1, v2, u[19], m[6]);
+	MONT_MAC(w0, w1, w2, u[20], m[5]);
+	MONT_MAC(t0, t1, t2, u[21], m[4]);
+	MONT_MAC(v0, v1, v2, u[22], m[3]);
+	MONT_MAC(w0, w1, w2, u[23], m[2]);
+	MONT_MAC(t0, t1, t2, u[24], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[25] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[25], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 26 */
+	MONT_MUL(s0, s1, s2, a[0], a[26]);
+	MONT_MUL(c0, c1, c2, a[1], a[25]);
+	MONT_MAC(s0, s1, s2, a[2], a[24]);
+	MONT_MAC(c0, c1, c2, a[3], a[23]);
+	MONT_MAC(s0, s1, s2, a[4], a[22]);
+	MONT_MAC(c0, c1, c2, a[5], a[21]);
+	MONT_MAC(s0, s1, s2, a[6], a[20]);
+	MONT_MAC(c0, c1, c2, a[7], a[19]);
+	MONT_MAC(s0, s1, s2, a[8], a[18]);
+	MONT_MAC(c0, c1, c2, a[9], a[17]);
+	MONT_MAC(s0, s1, s2, a[10], a[16]);
+	MONT_MAC(c0, c1, c2, a[11], a[15]);
+	MONT_MAC(s0, s1, s2, a[12], a[14]);
+	MONT_MAC(t0, t1, t2, a[13], a[13]);
+	MONT_MUL(v0, v1, v2, u[0], m[26]);
+	MONT_MUL(w0, w1, w2, u[1], m[25]);
+	MONT_MAC(t0, t1, t2, u[2], m[24]);
+	MONT_MAC(v0, v1, v2, u[3], m[23]);
+	MONT_MAC(w0, w1, w2, u[4], m[22]);
+	MONT_MAC(t0, t1, t2, u[5], m[21]);
+	MONT_MAC(v0, v1, v2, u[6], m[20]);
+	MONT_MAC(w0, w1, w2, u[7], m[19]);
+	MONT_MAC(t0, t1, t2, u[8], m[18]);
+	MONT_MAC(v0, v1, v2, u[9], m[17]);
+	MONT_MAC(w0, w1, w2, u[10], m[16]);
+	MONT_MAC(t0, t1, t2, u[11], m[15]);
+	MONT_MAC(v0, v1, v2, u[12], m[14]);
+	MONT_MAC(w0, w1, w2, u[13], m[13]);
+	MONT_MAC(t0, t1, t2, u[14], m[12]);
+	MONT_MAC(v0, v1, v2, u[15], m[11]);
+	MONT_MAC(w0, w1, w2, u[16], m[10]);
+	MONT_MAC(t0, t1, t2, u[17], m[9]);
+	MONT_MAC(v0, v1, v2, u[18], m[8]);
+	MONT_MAC(w0, w1, w2, u[19], m[7]);
+	MONT_MAC(t0, t1, t2, u[20], m[6]);
+	MONT_MAC(v0, v1, v2, u[21], m[5]);
+	MONT_MAC(w0, w1, w2, u[22], m[4]);
+	MONT_MAC(t0, t1, t2, u[23], m[3]);
+	MONT_MAC(v0, v1, v2, u[24], m[2]);
+	MONT_MAC(w0, w1, w2, u[25], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[26] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[26], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 27 */
+	MONT_MUL(s0, s1, s2, a[0], a[27]);
+	MONT_MUL(c0, c1, c2, a[1], a[26]);
+	MONT_MAC(s0, s1, s2, a[2], a[25]);
+	MONT_MAC(c0, c1, c2, a[3], a[24]);
+	MONT_MAC(s0, s1, s2, a[4], a[23]);
+	MONT_MAC(c0, c1, c2, a[5], a[22]);
+	MONT_MAC(s0, s1, s2, a[6], a[21]);
+	MONT_MAC(c0, c1, c2, a[7], a[20]);
+	MONT_MAC(s0, s1, s2, a[8], a[19]);
+	MONT_MAC(c0, c1, c2, a[9], a[18]);
+	MONT_MAC(s0, s1, s2, a[10], a[17]);
+	MONT_MAC(c0, c1, c2, a[11], a[16]);
+	MONT_MAC(s0, s1, s2, a[12], a[15]);
+	MONT_MAC(c0, c1, c2, a[13], a[14]);
+	MONT_MAC(t0, t1, t2, u[0], m[27]);
+	MONT_MUL(v0, v1, v2, u[1], m[26]);
+	MONT_MUL(w0, w1, w2, u[2], m[25]);
+	MONT_MAC(t0, t1, t2, u[3], m[24]);
+	MONT_MAC(v0, v1, v2, u[4], m[23]);
+	MONT_MAC(w0, w1, w2, u[5], m[22]);
+	MONT_MAC(t0, t1, t2, u[6], m[21]);
+	MONT_MAC(v0, v1, v2, u[7], m[20]);
+	MONT_MAC(w0, w1, w2, u[8], m[19]);
+	MONT_MAC(t0, t1, t2, u[9], m[18]);
+	MONT_MAC(v0, v1, v2, u[10], m[17]);
+	MONT_MAC(w0, w1, w2, u[11], m[16]);
+	MONT_MAC(t0, t1, t2, u[12], m[15]);
+	MONT_MAC(v0, v1, v2, u[13], m[14]);
+	MONT_MAC(w0, w1, w2, u[14], m[13]);
+	MONT_MAC(t0, t1, t2, u[15], m[12]);
+	MONT_MAC(v0, v1, v2, u[16], m[11]);
+	MONT_MAC(w0, w1, w2, u[17], m[10]);
+	MONT_MAC(t0, t1, t2, u[18], m[9]);
+	MONT_MAC(v0, v1, v2, u[19], m[8]);
+	MONT_MAC(w0, w1, w2, u[20], m[7]);
+	MONT_MAC(t0, t1, t2, u[21], m[6]);
+	MONT_MAC(v0, v1, v2, u[22], m[5]);
+	MONT_MAC(w0, w1, w2, u[23], m[4]);
+	MONT_MAC(t0, t1, t2, u[24], m[3]);
+	MONT_MAC(v0, v1, v2, u[25], m[2]);
+	MONT_MAC(w0, w1, w2, u[26], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[27] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[27], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 28 */
+	MONT_MUL(s0, s1, s2, a[0], a[28]);
+	MONT_MUL(c0, c1, c2, a[1], a[27]);
+	MONT_MAC(s0, s1, s2, a[2], a[26]);
+	MONT_MAC(c0, c1, c2, a[3], a[25]);
+	MONT_MAC(s0, s1, s2, a[4], a[24]);
+	MONT_MAC(c0, c1, c2, a[5], a[23]);
+	MONT_MAC(s0, s1, s2, a[6], a[22]);
+	MONT_MAC(c0, c1, c2, a[7], a[21]);
+	MONT_MAC(s0, s1, s2, a[8], a[20]);
+	MONT_MAC(c0, c1, c2, a[9], a[19]);
+	MONT_MAC(s0, s1, s2, a[10], a[18]);
+	MONT_MAC(c0, c1, c2, a[11], a[17]);
+	MONT_MAC(s0, s1, s2, a[12], a[16]);
+	MONT_MAC(c0, c1, c2, a[13], a[15]);
+	MONT_MAC(t0, t1, t2, a[14], a[14]);
+	MONT_MUL(v0, v1, v2, u[0], m[28]);
+	MONT_MUL(w0, w1, w2, u[1], m[27]);
+	MONT_MAC(t0, t1, t2, u[2], m[26]);
+	MONT_MAC(v0, v1, v2, u[3], m[25]);
+	MONT_MAC(w0, w1, w2, u[4], m[24]);
+	MONT_MAC(t0, t1, t2, u[5], m[23]);
+	MONT_MAC(v0, v1, v2, u[6], m[22]);
+	MONT_MAC(w0, w1, w2, u[7], m[21]);
+	MONT_MAC(t0, t1, t2, u[8], m[20]);
+	MONT_MAC(v0, v1, v2, u[9], m[19]);
+	MONT_MAC(w0, w1, w2, u[10], m[18]);
+	MONT_MAC(t0, t1, t2, u[11], m[17]);
+	MONT_MAC(v0, v1, v2, u[12], m[16]);
+	MONT_MAC(w0, w1, w2, u[13], m[15]);
+	MONT_MAC(t0, t1, t2, u[14], m[14]);
+	MONT_MAC(v0, v1, v2, u[15], m[13]);
+	MONT_MAC(w0, w1, w2, u[16], m[12]);
+	MONT_MAC(t0, t1, t2, u[17], m[11]);
+	MONT_MAC(v0, v1, v2, u[18], m[10]);
+	MONT_MAC(w0, w1, w2, u[19], m[9]);
+	MONT_MAC(t0, t1, t2, u[20], m[8]);
+	MONT_MAC(v0, v1, v2, u[21], m[7]);
+	MONT_MAC(w0, w1, w2, u[22], m[6]);
+	MONT_MAC(t0, t1, t2, u[23], m[5]);
+	MONT_MAC(v0, v1, v2, u[24], m[4]);
+	MONT_MAC(w0, w1, w2, u[25], m[3]);
+	MONT_MAC(t0, t1, t2, u[26], m[2]);
+	MONT_MAC(v0, v1, v2, u[27], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[28] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[28], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 29 */
+	MONT_MUL(s0, s1, s2, a[0], a[29]);
+	MONT_MUL(c0, c1, c2, a[1], a[28]);
+	MONT_MAC(s0, s1, s2, a[2], a[27]);
+	MONT_MAC(c0, c1, c2, a[3], a[26]);
+	MONT_MAC(s0, s1, s2, a[4], a[25]);
+	MONT_MAC(c0, c1, c2, a[5], a[24]);
+	MONT_MAC(s0, s1, s2, a[6], a[23]);
+	MONT_MAC(c0, c1, c2, a[7], a[22]);
+	MONT_MAC(s0, s1, s2, a[8], a[21]);
+	MONT_MAC(c0, c1, c2, a[9], a[20]);
+	MONT_MAC(s0, s1, s2, a[10], a[19]);
+	MONT_MAC(c0, c1, c2, a[11], a[18]);
+	MONT_MAC(s0, s1, s2, a[12], a[17]);
+	MONT_MAC(c0, c1, c2, a[13], a[16]);
+	MONT_MAC(s0, s1, s2, a[14], a[15]);
+	MONT_MAC(t0, t1, t2, u[0], m[29]);
+	MONT_MUL(v0, v1, v2, u[1], m[28]);
+	MONT_MUL(w0, w1, w2, u[2], m[27]);
+	MONT_MAC(t0, t1, t2, u[3], m[26]);
+	MONT_MAC(v0, v1, v2, u[4], m[25]);
+	MONT_MAC(w0, w1, w2, u[5], m[24]);
+	MONT_MAC(t0, t1, t2, u[6], m[23]);
+	MONT_MAC(v0, v1, v2, u[7], m[22]);
+	MONT_MAC(w0, w1, w2, u[8], m[21]);
+	MONT_MAC(t0, t1, t2, u[9], m[20]);
+	MONT_MAC(v0, v1, v2, u[10], m[19]);
+	MONT_MAC(w0, w1, w2, u[11], m[18]);
+	MONT_MAC(t0, t1, t2, u[12], m[17]);
+	MONT_MAC(v0, v1, v2, u[13], m[16]);
+	MONT_MAC(w0, w1, w2, u[14], m[15]);
+	MONT_MAC(t0, t1, t2, u[15], m[14]);
+	MONT_MAC(v0, v1, v2, u[16], m[13]);
+	MONT_MAC(w0, w1, w2, u[17], m[12]);
+	MONT_MAC(t0, t1, t2, u[18], m[11]);
+	MONT_MAC(v0, v1, v2, u[19], m[10]);
+	MONT_MAC(w0, w1, w2, u[20], m[9]);
+	MONT_MAC(t0, t1, t2, u[21], m[8]);
+	MONT_MAC(v0, v1, v2, u[22], m[7]);
+	MONT_MAC(w0, w1, w2, u[23], m[6]);
+	MONT_MAC(t0, t1, t2, u[24], m[5]);
+	MONT_MAC(v0, v1, v2, u[25], m[4]);
+	MONT_MAC(w0, w1, w2, u[26], m[3]);
+	MONT_MAC(t0, t1, t2, u[27], m[2]);
+	MONT_MAC(v0, v1, v2, u[28], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[29] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[29], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 30 */
+	MONT_MUL(s0, s1, s2, a[0], a[30]);
+	MONT_MUL(c0, c1, c2, a[1], a[29]);
+	MONT_MAC(s0, s1, s2, a[2], a[28]);
+	MONT_MAC(c0, c1, c2, a[3], a[27]);
+	MONT_MAC(s0, s1, s2, a[4], a[26]);
+	MONT_MAC(c0, c1, c2, a[5], a[25]);
+	MONT_MAC(s0, s1, s2, a[6], a[24]);
+	MONT_MAC(c0, c1, c2, a[7], a[23]);
+	MONT_MAC(s0, s1, s2, a[8], a[22]);
+	MONT_MAC(c0, c1, c2, a[9], a[21]);
+	MONT_MAC(s0, s1, s2, a[10], a[20]);
+	MONT_MAC(c0, c1, c2, a[11], a[19]);
+	MONT_MAC(s0, s1, s2, a[12], a[18]);
+	MONT_MAC(c0, c1, c2, a[13], a[17]);
+	MONT_MAC(s0, s1, s2, a[14], a[16]);
+	MONT_MAC(t0, t1, t2, a[15], a[15]);
+	MONT_MUL(v0, v1, v2, u[0], m[30]);
+	MONT_MUL(w0, w1, w2, u[1], m[29]);
+	MONT_MAC(t0, t1, t2, u[2], m[28]);
+	MONT_MAC(v0, v1, v2, u[3], m[27]);
+	MONT_MAC(w0, w1, w2, u[4], m[26]);
+	MONT_MAC(t0, t1, t2, u[5], m[25]);
+	MONT_MAC(v0, v1, v2, u[6], m[24]);
+	MONT_MAC(w0, w1, w2, u[7], m[23]);
+	MONT_MAC(t0, t1, t2, u[8], m[22]);
+	MONT_MAC(v0, v1, v2, u[9], m[21]);
+	MONT_MAC(w0, w1, w2, u[10], m[20]);
+	MONT_MAC(t0, t1, t2, u[11], m[19]);
+	MONT_MAC(v0, v1, v2, u[12], m[18]);
+	MONT_MAC(w0, w1, w2, u[13], m[17]);
+	MONT_MAC(t0, t1, t2, u[14], m[16]);
+	MONT_MAC(v0, v1, v2, u[15], m[15]);
+	MONT_MAC(w0, w1, w2, u[16], m[14]);
+	MONT_MAC(t0, t1, t2, u[17], m[13]);
+	MONT_MAC(v0, v1, v2, u[18], m[12]);
+	MONT_MAC(w0, w1, w2, u[19], m[11]);
+	MONT_MAC(t0, t1, t2, u[20], m[10]);
+	MONT_MAC(v0, v1, v2, u[21], m[9]);
+	MONT_MAC(w0, w1, w2, u[22], m[8]);
+	MONT_MAC(t0, t1, t2, u[23], m[7]);
+	MONT_MAC(v0, v1, v2, u[24], m[6]);
+	MONT_MAC(w0, w1, w2, u[25], m[5]);
+	MONT_MAC(t0, t1, t2, u[26], m[4]);
+	MONT_MAC(v0, v1, v2, u[27], m[3]);
+	MONT_MAC(w0, w1, w2, u[28], m[2]);
+	MONT_MAC(t0, t1, t2, u[29], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[30] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[30], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 31 */
+	MONT_MUL(s0, s1, s2, a[0], a[31]);
+	MONT_MUL(c0, c1, c2, a[1], a[30]);
+	MONT_MAC(s0, s1, s2, a[2], a[29]);
+	MONT_MAC(c0, c1, c2, a[3], a[28]);
+	MONT_MAC(s0, s1, s2, a[4], a[27]);
+	MONT_MAC(c0, c1, c2, a[5], a[26]);
+	MONT_MAC(s0, s1, s2, a[6], a[25]);
+	MONT_MAC(c0, c1, c2, a[7], a[24]);
+	MONT_MAC(s0, s1, s2, a[8], a[23]);
+	MONT_MAC(c0, c1, c2, a[9], a[22]);
+	MONT_MAC(s0, s1, s2, a[10], a[21]);
+	MONT_MAC(c0, c1, c2, a[11], a[20]);
+	MONT_MAC(s0, s1, s2, a[12], a[19]);
+	MONT_MAC(c0, c1, c2, a[13], a[18]);
+	MONT_MAC(s0, s1, s2, a[14], a[17]);
+	MONT_MAC(c0, c1, c2, a[15], a[16]);
+	MONT_MAC(t0, t1, t2, u[0], m[31]);
+	MONT_MUL(v0, v1, v2, u[1], m[30]);
+	MONT_MUL(w0, w1, w2, u[2], m[29]);
+	MONT_MAC(t0, t1, t2, u[3], m[28]);
+	MONT_MAC(v0, v1, v2, u[4], m[27]);
+	MONT_MAC(w0, w1, w2, u[5], m[26]);
+	MONT_MAC(t0, t1, t2, u[6], m[25]);
+	MONT_MAC(v0, v1, v2, u[7], m[24]);
+	MONT_MAC(w0, w1, w2, u[8], m[23]);
+	MONT_MAC(t0, t1, t2, u[9], m[22]);
+	MONT_MAC(v0, v1, v2, u[10], m[21]);
+	MONT_MAC(w0, w1, w2, u[11], m[20]);
+	MONT_MAC(t0, t1, t2, u[12], m[19]);
+	MONT_MAC(v0, v1, v2, u[13], m[18]);
+	MONT_MAC(w0, w1, w2, u[14], m[17]);
+	MONT_MAC(t0, t1, t2, u[15], m[16]);
+	MONT_MAC(v0, v1, v2, u[16], m[15]);
+	MONT_MAC(w0, w1, w2, u[17], m[14]);
+	MONT_MAC(t0, t1, t2, u[18], m[13]);
+	MONT_MAC(v0, v1, v2, u[19], m[12]);
+	MONT_MAC(w0, w1, w2, u[20], m[11]);
+	MONT_MAC(t0, t1, t2, u[21], m[10]);
+	MONT_MAC(v0, v1, v2, u[22], m[9]);
+	MONT_MAC(w0, w1, w2, u[23], m[8]);
+	MONT_MAC(t0, t1, t2, u[24], m[7]);
+	MONT_MAC(v0, v1, v2, u[25], m[6]);
+	MONT_MAC(w0, w1, w2, u[26], m[5]);
+	MONT_MAC(t0, t1, t2, u[27], m[4]);
+	MONT_MAC(v0, v1, v2, u[28], m[3]);
+	MONT_MAC(w0, w1, w2, u[29], m[2]);
+	MONT_MAC(t0, t1, t2, u[30], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[31] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[31], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 32 */
+	MONT_MUL(s0, s1, s2, a[0], a[32]);
+	MONT_MUL(c0, c1, c2, a[1], a[31]);
+	MONT_MAC(s0, s1, s2, a[2], a[30]);
+	MONT_MAC(c0, c1, c2, a[3], a[29]);
+	MONT_MAC(s0, s1, s2, a[4], a[28]);
+	MONT_MAC(c0, c1, c2, a[5], a[27]);
+	MONT_MAC(s0, s1, s2, a[6], a[26]);
+	MONT_MAC(c0, c1, c2, a[7], a[25]);
+	MONT_MAC(s0, s1, s2, a[8], a[24]);
+	MONT_MAC(c0, c1, c2, a[9], a[23]);
+	MONT_MAC(s0, s1, s2, a[10], a[22]);
+	MONT_MAC(c0, c1, c2, a[11], a[21]);
+	MONT_MAC(s0, s1, s2, a[12], a[20]);
+	MONT_MAC(c0, c1, c2, a[13], a[19]);
+	MONT_MAC(s0, s1, s2, a[14], a[18]);
+	MONT_MAC(c0, c1, c2, a[15], a[17]);
+	MONT_MAC(t0, t1, t2, a[16], a[16]);
+	MONT_MUL(v0, v1, v2, u[0], m[32]);
+	MONT_MUL(w0, w1, w2, u[1], m[31]);
+	MONT_MAC(t0, t1, t2, u[2], m[30]);
+	MONT_MAC(v0, v1, v2, u[3], m[29]);
+	MONT_MAC(w0, w1, w2, u[4], m[28]);
+	MONT_MAC(t0, t1, t2, u[5], m[27]);
+	MONT_MAC(v0, v1, v2, u[6], m[26]);
+	MONT_MAC(w0, w1, w2, u[7], m[25]);
+	MONT_MAC(t0, t1, t2, u[8], m[24]);
+	MONT_MAC(v0, v1, v2, u[9], m[23]);
+	MONT_MAC(w0, w1, w2, u[10], m[22]);
+	MONT_MAC(t0, t1, t2, u[11], m[21]);
+	MONT_MAC(v0, v1, v2, u[12], m[20]);
+	MONT_MAC(w0, w1, w2, u[13], m[19]);
+	MONT_MAC(t0, t1, t2, u[14], m[18]);
+	MONT_MAC(v0, v1, v2, u[15], m[17]);
+	MONT_MAC(w0, w1, w2, u[16], m[16]);
+	MONT_MAC(t0, t1, t2, u[17], m[15]);
+	MONT_MAC(v0, v1, v2, u[18], m[14]);
+	MONT_MAC(w0, w1, w2, u[19], m[13]);
+	MONT_MAC(t0, t1, t2, u[20], m[12]);
+	MONT_MAC(v0, v1, v2, u[21], m[11]);
+	MONT_MAC(w0, w1, w2, u[22], m[10]);
+	MONT_MAC(t0, t1, t2, u[23], m[9]);
+	MONT_MAC(v0, v1, v2, u[24], m[8]);
+	MONT_MAC(w0, w1, w2, u[25], m[7]);
+	MONT_MAC(t0, t1, t2, u[26], m[6]);
+	MONT_MAC(v0, v1, v2, u[27], m[5]);
+	MONT_MAC(w0, w1, w2, u[28], m[4]);
+	MONT_MAC(t0, t1, t2, u[29], m[3]);
+	MONT_MAC(v0, v1, v2, u[30], m[2]);
+	MONT_MAC(w0, w1, w2, u[31], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[32] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[32], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 33 */
+	MONT_MUL(s0, s1, s2, a[0], a[33]);
+	MONT_MUL(c0, c1, c2, a[1], a[32]);
+	MONT_MAC(s0, s1, s2, a[2], a[31]);
+	MONT_MAC(c0, c1, c2, a[3], a[30]);
+	MONT_MAC(s0, s1, s2, a[4], a[29]);
+	MONT_MAC(c0, c1, c2, a[5], a[28]);
+	MONT_MAC(s0, s1, s2, a[6], a[27]);
+	MONT_MAC(c0, c1, c2, a[7], a[26]);
+	MONT_MAC(s0, s1, s2, a[8], a[25]);
+	MONT_MAC(c0, c1, c2, a[9], a[24]);
+	MONT_MAC(s0, s1, s2, a[10], a[23]);
+	MONT_MAC(c0, c1, c2, a[11], a[22]);
+	MONT_MAC(s0, s1, s2, a[12], a[21]);
+	MONT_MAC(c0, c1, c2, a[13], a[20]);
+	MONT_MAC(s0, s1, s2, a[14], a[19]);
+	MONT_MAC(c0, c1, c2, a[15], a[18]);
+	MONT_MAC(s0, s1, s2, a[16], a[17]);
+	MONT_MAC(t0, t1, t2, u[0], m[33]);
+	MONT_MUL(v0, v1, v2, u[1], m[32]);
+	MONT_MUL(w0, w1, w2, u[2], m[31]);
+	MONT_MAC(t0, t1, t2, u[3], m[30]);
+	MONT_MAC(v0, v1, v2, u[4], m[29]);
+	MONT_MAC(w0, w1, w2, u[5], m[28]);
+	MONT_MAC(t0, t1, t2, u[6], m[27]);
+	MONT_MAC(v0, v1, v2, u[7], m[26]);
+	MONT_MAC(w0, w1, w2, u[8], m[25]);
+	MONT_MAC(t0, t1, t2, u[9], m[24]);
+	MONT_MAC(v0, v1, v2, u[10], m[23]);
+	MONT_MAC(w0, w1, w2, u[11], m[22]);
+	MONT_MAC(t0, t1, t2, u[12], m[21]);
+	MONT_MAC(v0, v1, v2, u[13], m[20]);
+	MONT_MAC(w0, w1, w2, u[14], m[19]);
+	MONT_MAC(t0, t1, t2, u[15], m[18]);
+	MONT_MAC(v0, v1, v2, u[16], m[17]);
+	MONT_MAC(w0, w1, w2, u[17], m[16]);
+	MONT_MAC(t0, t1, t2, u[18], m[15]);
+	MONT_MAC(v0, v1, v2, u[19], m[14]);
+	MONT_MAC(w0, w1, w2, u[20], m[13]);
+	MONT_MAC(t0, t1, t2, u[21], m[12]);
+	MONT_MAC(v0, v1, v2, u[22], m[11]);
+	MONT_MAC(w0, w1, w2, u[23], m[10]);
+	MONT_MAC(t0, t1, t2, u[24], m[9]);
+	MONT_MAC(v0, v1, v2, u[25], m[8]);
+	MONT_MAC(w0, w1, w2, u[26], m[7]);
+	MONT_MAC(t0, t1, t2, u[27], m[6]);
+	MONT_MAC(v0, v1, v2, u[28], m[5]);
+	MONT_MAC(w0, w1, w2, u[29], m[4]);
+	MONT_MAC(t0, t1, t2, u[30], m[3]);
+	MONT_MAC(v0, v1, v2, u[31], m[2]);
+	MONT_MAC(w0, w1, w2, u[32], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[33] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[33], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 34 */
+	MONT_MUL(s0, s1, s2, a[0], a[34]);
+	MONT_MUL(c0, c1, c2, a[1], a[33]);
+	MONT_MAC(s0, s1, s2, a[2], a[32]);
+	MONT_MAC(c0, c1, c2, a[3], a[31]);
+	MONT_MAC(s0, s1, s2, a[4], a[30]);
+	MONT_MAC(c0, c1, c2, a[5], a[29]);
+	MONT_MAC(s0, s1, s2, a[6], a[28]);
+	MONT_MAC(c0, c1, c2, a[7], a[27]);
+	MONT_MAC(s0, s1, s2, a[8], a[26]);
+	MONT_MAC(c0, c1, c2, a[9], a[25]);
+	MONT_MAC(s0, s1, s2, a[10], a[24]);
+	MONT_MAC(c0, c1, c2, a[11], a[23]);
+	MONT_MAC(s0, s1, s2, a[12], a[22]);
+	MONT_MAC(c0, c1, c2, a[13], a[21]);
+	MONT_MAC(s0, s1, s2, a[14], a[20]);
+	MONT_MAC(c0, c1, c2, a[15], a[19]);
+	MONT_MAC(s0, s1, s2, a[16], a[18]);
+	MONT_MAC(t0, t1, t2, a[17], a[17]);
+	MONT_MUL(v0, v1, v2, u[0], m[34]);
+	MONT_MUL(w0, w1, w2, u[1], m[33]);
+	MONT_MAC(t0, t1, t2, u[2], m[32]);
+	MONT_MAC(v0, v1, v2, u[3], m[31]);
+	MONT_MAC(w0, w1, w2, u[4], m[30]);
+	MONT_MAC(t0, t1, t2, u[5], m[29]);
+	MONT_MAC(v0, v1, v2, u[6], m[28]);
+	MONT_MAC(w0, w1, w2, u[7], m[27]);
+	MONT_MAC(t0, t1, t2, u[8], m[26]);
+	MONT_MAC(v0, v1, v2, u[9], m[25]);
+	MONT_MAC(w0, w1, w2, u[10], m[24]);
+	MONT_MAC(t0, t1, t2, u[11], m[23]);
+	MONT_MAC(v0, v1, v2, u[12], m[22]);
+	MONT_MAC(w0, w1, w2, u[13], m[21]);
+	MONT_MAC(t0, t1, t2, u[14], m[20]);
+	MONT_MAC(v0, v1, v2, u[15], m[19]);
+	MONT_MAC(w0, w1, w2, u[16], m[18]);
+	MONT_MAC(t0, t1, t2, u[17], m[17]);
+	MONT_MAC(v0, v1, v2, u[18], m[16]);
+	MONT_MAC(w0, w1, w2, u[19], m[15]);
+	MONT_MAC(t0, t1, t2, u[20], m[14]);
+	MONT_MAC(v0, v1, v2, u[21], m[13]);
+	MONT_MAC(w0, w1, w2, u[22], m[12]);
+	MONT_MAC(t0, t1, t2, u[23], m[11]);
+	MONT_MAC(v0, v1, v2, u[24], m[10]);
+	MONT_MAC(w0, w1, w2, u[25], m[9]);
+	MONT_MAC(t0, t1, t2, u[26], m[8]);
+	MONT_MAC(v0, v1, v2, u[27], m[7]);
+	MONT_MAC(w0, w1, w2, u[28], m[6]);
+	MONT_MAC(t0, t1, t2, u[29], m[5]);
+	MONT_MAC(v0, v1, v2, u[30], m[4]);
+	MONT_MAC(w0, w1, w2, u[31], m[3]);
+	MONT_MAC(t0, t1, t2, u[32], m[2]);
+	MONT_MAC(v0, v1, v2, u[33], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[34] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[34], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 35 */
+	MONT_MUL(s0, s1, s2, a[0], a[35]);
+	MONT_MUL(c0, c1, c2, a[1], a[34]);
+	MONT_MAC(s0, s1, s2, a[2], a[33]);
+	MONT_MAC(c0, c1, c2, a[3], a[32]);
+	MONT_MAC(s0, s1, s2, a[4], a[31]);
+	MONT_MAC(c0, c1, c2, a[5], a[30]);
+	MONT_MAC(s0, s1, s2, a[6], a[29]);
+	MONT_MAC(c0, c1, c2, a[7], a[28]);
+	MONT_MAC(s0, s1, s2, a[8], a[27]);
+	MONT_MAC(c0, c1, c2, a[9], a[26]);
+	MONT_MAC(s0, s1, s2, a[10], a[25]);
+	MONT_MAC(c0, c1, c2, a[11], a[24]);
+	MONT_MAC(s0, s1, s2, a[12], a[23]);
+	MONT_MAC(c0, c1, c2, a[13], a[22]);
+	MONT_MAC(s0, s1, s2, a[14], a[21]);
+	MONT_MAC(c0, c1, c2, a[15], a[20]);
+	MONT_MAC(s0, s1, s2, a[16], a[19]);
+	MONT_MAC(c0, c1, c2, a[17], a[18]);
+	MONT_MAC(t0, t1, t2, u[0], m[35]);
+	MONT_MUL(v0, v1, v2, u[1], m[34]);
+	MONT_MUL(w0, w1, w2, u[2], m[33]);
+	MONT_MAC(t0, t1, t2, u[3], m[32]);
+	MONT_MAC(v0, v1, v2, u[4], m[31]);
+	MONT_MAC(w0, w1, w2, u[5], m[30]);
+	MONT_MAC(t0, t1, t2, u[6], m[29]);
+	MONT_MAC(v0, v1, v2, u[7], m[28]);
+	MONT_MAC(w0, w1, w2, u[8], m[27]);
+	MONT_MAC(t0, t1, t2, u[9], m[26]);
+	MONT_MAC(v0, v1, v2, u[10], m[25]);
+	MONT_MAC(w0, w1, w2, u[11], m[24]);
+	MONT_MAC(t0, t1, t2, u[12], m[23]);
+	MONT_MAC(v0, v1, v2, u[13], m[22]);
+	MONT_MAC(w0, w1, w2, u[14], m[21]);
+	MONT_MAC(t0, t1, t2, u[15], m[20]);
+	MONT_MAC(v0, v1, v2, u[16], m[19]);
+	MONT_MAC(w0, w1, w2, u[17], m[18]);
+	MONT_MAC(t0, t1, t2, u[18], m[17]);
+	MONT_MAC(v0, v1, v2, u[19], m[16]);
+	MONT_MAC(w0, w1, w2, u[20], m[15]);
+	MONT_MAC(t0, t1, t2, u[21], m[14]);
+	MONT_MAC(v0, v1, v2, u[22], m[13]);
+	MONT_MAC(w0, w1, w2, u[23], m[12]);
+	MONT_MAC(t0, t1, t2, u[24], m[11]);
+	MONT_MAC(v0, v1, v2, u[25], m[10]);
+	MONT_MAC(w0, w1, w2, u[26], m[9]);
+	MONT_MAC(t0, t1, t2, u[27], m[8]);
+	MONT_MAC(v0, v1, v2, u[28], m[7]);
+	MONT_MAC(w0, w1, w2, u[29], m[6]);
+	MONT_MAC(t0, t1, t2, u[30], m[5]);
+	MONT_MAC(v0, v1, v2, u[31], m[4]);
+	MONT_MAC(w0, w1, w2, u[32], m[3]);
+	MONT_MAC(t0, t1, t2, u[33], m[2]);
+	MONT_MAC(v0, v1, v2, u[34], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[35] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[35], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 36 */
+	MONT_MUL(s0, s1, s2, a[0], a[36]);
+	MONT_MUL(c0, c1, c2, a[1], a[35]);
+	MONT_MAC(s0, s1, s2, a[2], a[34]);
+	MONT_MAC(c0, c1, c2, a[3], a[33]);
+	MONT_MAC(s0, s1, s2, a[4], a[32]);
+	MONT_MAC(c0, c1, c2, a[5], a[31]);
+	MONT_MAC(s0, s1, s2, a[6], a[30]);
+	MONT_MAC(c0, c1, c2, a[7], a[29]);
+	MONT_MAC(s0, s1, s2, a[8], a[28]);
+	MONT_MAC(c0, c1, c2, a[9], a[27]);
+	MONT_MAC(s0, s1, s2, a[10], a[26]);
+	MONT_MAC(c0, c1, c2, a[11], a[25]);
+	MONT_MAC(s0, s1, s2, a[12], a[24]);
+	MONT_MAC(c0, c1, c2, a[13], a[23]);
+	MONT_MAC(s0, s1, s2, a[14], a[22]);
+	MONT_MAC(c0, c1, c2, a[15], a[21]);
+	MONT_MAC(s0, s1, s2, a[16], a[20]);
+	MONT_MAC(c0, c1, c2, a[17], a[19]);
+	MONT_MAC(t0, t1, t2, a[18], a[18]);
+	MONT_MUL(v0, v1, v2, u[0], m[36]);
+	MONT_MUL(w0, w1, w2, u[1], m[35]);
+	MONT_MAC(t0, t1, t2, u[2], m[34]);
+	MONT_MAC(v0, v1, v2, u[3], m[33]);
+	MONT_MAC(w0, w1, w2, u[4], m[32]);
+	MONT_MAC(t0, t1, t2, u[5], m[31]);
+	MONT_MAC(v0, v1, v2, u[6], m[30]);
+	MONT_MAC(w0, w1, w2, u[7], m[29]);
+	MONT_MAC(t0, t1, t2, u[8], m[28]);
+	MONT_MAC(v0, v1, v2, u[9], m[27]);
+	MONT_MAC(w0, w1, w2, u[10], m[26]);
+	MONT_MAC(t0, t1, t2, u[11], m[25]);
+	MONT_MAC(v0, v1, v2, u[12], m[24]);
+	MONT_MAC(w0, w1, w2, u[13], m[23]);
+	MONT_MAC(t0, t1, t2, u[14], m[22]);
+	MONT_MAC(v0, v1, v2, u[15], m[21]);
+	MONT_MAC(w0, w1, w2, u[16], m[20]);
+	MONT_MAC(t0, t1, t2, u[17], m[19]);
+	MONT_MAC(v0, v1, v2, u[18], m[18]);
+	MONT_MAC(w0, w1, w2, u[19], m[17]);
+	MONT_MAC(t0, t1, t2, u[20], m[16]);
+	MONT_MAC(v0, v1, v2, u[21], m[15]);
+	MONT_MAC(w0, w1, w2, u[22], m[14]);
+	MONT_MAC(t0, t1, t2, u[23], m[13]);
+	MONT_MAC(v0, v1, v2, u[24], m[12]);
+	MONT_MAC(w0, w1, w2, u[25], m[11]);
+	MONT_MAC(t0, t1, t2, u[26], m[10]);
+	MONT_MAC(v0, v1, v2, u[27], m[9]);
+	MONT_MAC(w0, w1, w2, u[28], m[8]);
+	MONT_MAC(t0, t1, t2, u[29], m[7]);
+	MONT_MAC(v0, v1, v2, u[30], m[6]);
+	MONT_MAC(w0, w1, w2, u[31], m[5]);
+	MONT_MAC(t0, t1, t2, u[32], m[4]);
+	MONT_MAC(v0, v1, v2, u[33], m[3]);
+	MONT_MAC(w0, w1, w2, u[34], m[2]);
+	MONT_MAC(t0, t1, t2, u[35], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[36] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[36], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 37 */
+	MONT_MUL(s0, s1, s2, a[0], a[37]);
+	MONT_MUL(c0, c1, c2, a[1], a[36]);
+	MONT_MAC(s0, s1, s2, a[2], a[35]);
+	MONT_MAC(c0, c1, c2, a[3], a[34]);
+	MONT_MAC(s0, s1, s2, a[4], a[33]);
+	MONT_MAC(c0, c1, c2, a[5], a[32]);
+	MONT_MAC(s0, s1, s2, a[6], a[31]);
+	MONT_MAC(c0, c1, c2, a[7], a[30]);
+	MONT_MAC(s0, s1, s2, a[8], a[29]);
+	MONT_MAC(c0, c1, c2, a[9], a[28]);
+	MONT_MAC(s0, s1, s2, a[10], a[27]);
+	MONT_MAC(c0, c1, c2, a[11], a[26]);
+	MONT_MAC(s0, s1, s2, a[12], a[25]);
+	MONT_MAC(c0, c1, c2, a[13], a[24]);
+	MONT_MAC(s0, s1, s2, a[14], a[23]);
+	MONT_MAC(c0, c1, c2, a[15], a[22]);
+	MONT_MAC(s0, s1, s2, a[16], a[21]);
+	MONT_MAC(c0, c1, c2, a[17], a[20]);
+	MONT_MAC(s0, s1, s2, a[18], a[19]);
+	MONT_MAC(t0, t1, t2, u[0], m[37]);
+	MONT_MUL(v0, v1, v2, u[1], m[36]);
+	MONT_MUL(w0, w1, w2, u[2], m[35]);
+	MONT_MAC(t0, t1, t2, u[3], m[34]);
+	MONT_MAC(v0, v1, v2, u[4], m[33]);
+	MONT_MAC(w0, w1, w2, u[5], m[32]);
+	MONT_MAC(t0, t1, t2, u[6], m[31]);
+	MONT_MAC(v0, v1, v2, u[7], m[30]);
+	MONT_MAC(w0, w1, w2, u[8], m[29]);
+	MONT_MAC(t0, t1, t2, u[9], m[28]);
+	MONT_MAC(v0, v1, v2, u[10], m[27]);
+	MONT_MAC(w0, w1, w2, u[11], m[26]);
+	MONT_MAC(t0, t1, t2, u[12], m[25]);
+	MONT_MAC(v0, v1, v2, u[13], m[24]);
+	MONT_MAC(w0, w1, w2, u[14], m[23]);
+	MONT_MAC(t0, t1, t2, u[15], m[22]);
+	MONT_MAC(v0, v1, v2, u[16], m[21]);
+	MONT_MAC(w0, w1, w2, u[17], m[20]);
+	MONT_MAC(t0, t1, t2, u[18], m[19]);
+	MONT_MAC(v0, v1, v2, u[19], m[18]);
+	MONT_MAC(w0, w1, w2, u[20], m[17]);
+	MONT_MAC(t0, t1, t2, u[21], m[16]);
+	MONT_MAC(v0, v1, v2, u[22], m[15]);
+	MONT_MAC(w0, w1, w2, u[23], m[14]);
+	MONT_MAC(t0, t1, t2, u[24], m[13]);
+	MONT_MAC(v0, v1, v2, u[25], m[12]);
+	MONT_MAC(w0, w1, w2, u[26], m[11]);
+	MONT_MAC(t0, t1, t2, u[27], m[10]);
+	MONT_MAC(v0, v1, v2, u[28], m[9]);
+	MONT_MAC(w0, w1, w2, u[29], m[8]);
+	MONT_MAC(t0, t1, t2, u[30], m[7]);
+	MONT_MAC(v0, v1, v2, u[31], m[6]);
+	MONT_MAC(w0, w1, w2, u[32], m[5]);
+	MONT_MAC(t0, t1, t2, u[33], m[4]);
+	MONT_MAC(v0, v1, v2, u[34], m[3]);
+	MONT_MAC(w0, w1, w2, u[35], m[2]);
+	MONT_MAC(t0, t1, t2, u[36], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[37] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[37], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 38 */
+	MONT_MUL(s0, s1, s2, a[0], a[38]);
+	MONT_MUL(c0, c1, c2, a[1], a[37]);
+	MONT_MAC(s0, s1, s2, a[2], a[36]);
+	MONT_MAC(c0, c1, c2, a[3], a[35]);
+	MONT_MAC(s0, s1, s2, a[4], a[34]);
+	MONT_MAC(c0, c1, c2, a[5], a[33]);
+	MONT_MAC(s0, s1, s2, a[6], a[32]);
+	MONT_MAC(c0, c1, c2, a[7], a[31]);
+	MONT_MAC(s0, s1, s2, a[8], a[30]);
+	MONT_MAC(c0, c1, c2, a[9], a[29]);
+	MONT_MAC(s0, s1, s2, a[10], a[28]);
+	MONT_MAC(c0, c1, c2, a[11], a[27]);
+	MONT_MAC(s0, s1, s2, a[12], a[26]);
+	MONT_MAC(c0, c1, c2, a[13], a[25]);
+	MONT_MAC(s0, s1, s2, a[14], a[24]);
+	MONT_MAC(c0, c1, c2, a[15], a[23]);
+	MONT_MAC(s0, s1, s2, a[16], a[22]);
+	MONT_MAC(c0, c1, c2, a[17], a[21]);
+	MONT_MAC(s0, s1, s2, a[18], a[20]);
+	MONT_MAC(t0, t1, t2, a[19], a[19]);
+	MONT_MUL(v0, v1, v2, u[0], m[38]);
+	MONT_MUL(w0, w1, w2, u[1], m[37]);
+	MONT_MAC(t0, t1, t2, u[2], m[36]);
+	MONT_MAC(v0, v1, v2, u[3], m[35]);
+	MONT_MAC(w0, w1, w2, u[4], m[34]);
+	MONT_MAC(t0, t1, t2, u[5], m[33]);
+	MONT_MAC(v0, v1, v2, u[6], m[32]);
+	MONT_MAC(w0, w1, w2, u[7], m[31]);
+	MONT_MAC(t0, t1, t2, u[8], m[30]);
+	MONT_MAC(v0, v1, v2, u[9], m[29]);
+	MONT_MAC(w0, w1, w2, u[10], m[28]);
+	MONT_MAC(t0, t1, t2, u[11], m[27]);
+	MONT_MAC(v0, v1, v2, u[12], m[26]);
+	MONT_MAC(w0, w1, w2, u[13], m[25]);
+	MONT_MAC(t0, t1, t2, u[14], m[24]);
+	MONT_MAC(v0, v1, v2, u[15], m[23]);
+	MONT_MAC(w0, w1, w2, u[16], m[22]);
+	MONT_MAC(t0, t1, t2, u[17], m[21]);
+	MONT_MAC(v0, v1, v2, u[18], m[20]);
+	MONT_MAC(w0, w1, w2, u[19], m[19]);
+	MONT_MAC(t0, t1, t2, u[20], m[18]);
+	MONT_MAC(v0, v1, v2, u[21], m[17]);
+	MONT_MAC(w0, w1, w2, u[22], m[16]);
+	MONT_MAC(t0, t1, t2, u[23], m[15]);
+	MONT_MAC(v0, v1, v2, u[24], m[14]);
+	MONT_MAC(w0, w1, w2, u[25], m[13]);
+	MONT_MAC(t0, t1, t2, u[26], m[12]);
+	MONT_MAC(v0, v1, v2, u[27], m[11]);
+	MONT_MAC(w0, w1, w2, u[28], m[10]);
+	MONT_MAC(t0, t1, t2, u[29], m[9]);
+	MONT_MAC(v0, v1, v2, u[30], m[8]);
+	MONT_MAC(w0, w1, w2, u[31], m[7]);
+	MONT_MAC(t0, t1, t2, u[32], m[6]);
+	MONT_MAC(v0, v1, v2, u[33], m[5]);
+	MONT_MAC(w0, w1, w2, u[34], m[4]);
+	MONT_MAC(t0, t1, t2, u[35], m[3]);
+	MONT_MAC(v0, v1, v2, u[36], m[2]);
+	MONT_MAC(w0, w1, w2, u[37], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[38] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[38], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 39 */
+	MONT_MUL(s0, s1, s2, a[0], a[39]);
+	MONT_MUL(c0, c1, c2, a[1], a[38]);
+	MONT_MAC(s0, s1, s2, a[2], a[37]);
+	MONT_MAC(c0, c1, c2, a[3], a[36]);
+	MONT_MAC(s0, s1, s2, a[4], a[35]);
+	MONT_MAC(c0, c1, c2, a[5], a[34]);
+	MONT_MAC(s0, s1, s2, a[6], a[33]);
+	MONT_MAC(c0, c1, c2, a[7], a[32]);
+	MONT_MAC(s0, s1, s2, a[8], a[31]);
+	MONT_MAC(c0, c1, c2, a[9], a[30]);
+	MONT_MAC(s0, s1, s2, a[10], a[29]);
+	MONT_MAC(c0, c1, c2, a[11], a[28]);
+	MONT_MAC(s0, s1, s2, a[12], a[27]);
+	MONT_MAC(c0, c1, c2, a[13], a[26]);
+	MONT_MAC(s0, s1, s2, a[14], a[25]);
+	MONT_MAC(c0, c1, c2, a[15], a[24]);
+	MONT_MAC(s0, s1, s2, a[16], a[23]);
+	MONT_MAC(c0, c1, c2, a[17], a[22]);
+	MONT_MAC(s0, s1, s2, a[18], a[21]);
+	MONT_MAC(c0, c1, c2, a[19], a[20]);
+	MONT_MAC(t0, t1, t2, u[0], m[39]);
+	MONT_MUL(v0, v1, v2, u[1], m[38]);
+	MONT_MUL(w0, w1, w2, u[2], m[37]);
+	MONT_MAC(t0, t1, t2, u[3], m[36]);
+	MONT_MAC(v0, v1, v2, u[4], m[35]);
+	MONT_MAC(w0, w1, w2, u[5], m[34]);
+	MONT_MAC(t0, t1, t2, u[6], m[33]);
+	MONT_MAC(v0, v1, v2, u[7], m[32]);
+	MONT_MAC(w0, w1, w2, u[8], m[31]);
+	MONT_MAC(t0, t1, t2, u[9], m[30]);
+	MONT_MAC(v0, v1, v2, u[10], m[29]);
+	MONT_MAC(w0, w1, w2, u[11], m[28]);
+	MONT_MAC(t0, t1, t2, u[12], m[27]);
+	MONT_MAC(v0, v1, v2, u[13], m[26]);
+	MONT_MAC(w0, w1, w2, u[14], m[25]);
+	MONT_MAC(t0, t1, t2, u[15], m[24]);
+	MONT_MAC(v0, v1, v2, u[16], m[23]);
+	MONT_MAC(w0, w1, w2, u[17], m[22]);
+	MONT_MAC(t0, t1, t2, u[18], m[21]);
+	MONT_MAC(v0, v1, v2, u[19], m[20]);
+	MONT_MAC(w0, w1, w2, u[20], m[19]);
+	MONT_MAC(t0, t1, t2, u[21], m[18]);
+	MONT_MAC(v0, v1, v2, u[22], m[17]);
+	MONT_MAC(w0, w1, w2, u[23], m[16]);
+	MONT_MAC(t0, t1, t2, u[24], m[15]);
+	MONT_MAC(v0, v1, v2, u[25], m[14]);
+	MONT_MAC(w0, w1, w2, u[26], m[13]);
+	MONT_MAC(t0, t1, t2, u[27], m[12]);
+	MONT_MAC(v0, v1, v2, u[28], m[11]);
+	MONT_MAC(w0, w1, w2, u[29], m[10]);
+	MONT_MAC(t0, t1, t2, u[30], m[9]);
+	MONT_MAC(v0, v1, v2, u[31], m[8]);
+	MONT_MAC(w0, w1, w2, u[32], m[7]);
+	MONT_MAC(t0, t1, t2, u[33], m[6]);
+	MONT_MAC(v0, v1, v2, u[34], m[5]);
+	MONT_MAC(w0, w1, w2, u[35], m[4]);
+	MONT_MAC(t0, t1, t2, u[36], m[3]);
+	MONT_MAC(v0, v1, v2, u[37], m[2]);
+	MONT_MAC(w0, w1, w2, u[38], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[39] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[39], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 40 */
+	MONT_MUL(s0, s1, s2, a[0], a[40]);
+	MONT_MUL(c0, c1, c2, a[1], a[39]);
+	MONT_MAC(s0, s1, s2, a[2], a[38]);
+	MONT_MAC(c0, c1, c2, a[3], a[37]);
+	MONT_MAC(s0, s1, s2, a[4], a[36]);
+	MONT_MAC(c0, c1, c2, a[5], a[35]);
+	MONT_MAC(s0, s1, s2, a[6], a[34]);
+	MONT_MAC(c0, c1, c2, a[7], a[33]);
+	MONT_MAC(s0, s1, s2, a[8], a[32]);
+	MONT_MAC(c0, c1, c2, a[9], a[31]);
+	MONT_MAC(s0, s1, s2, a[10], a[30]);
+	MONT_MAC(c0, c1, c2, a[11], a[29]);
+	MONT_MAC(s0, s1, s2, a[12], a[28]);
+	MONT_MAC(c0, c1, c2, a[13], a[27]);
+	MONT_MAC(s0, s1, s2, a[14], a[26]);
+	MONT_MAC(c0, c1, c2, a[15], a[25]);
+	MONT_MAC(s0, s1, s2, a[16], a[24]);
+	MONT_MAC(c0, c1, c2, a[17], a[23]);
+	MONT_MAC(s0, s1, s2, a[18], a[22]);
+	MONT_MAC(c0, c1, c2, a[19], a[21]);
+	MONT_MAC(t0, t1, t2, a[20], a[20]);
+	MONT_MUL(v0, v1, v2, u[0], m[40]);
+	MONT_MUL(w0, w1, w2, u[1], m[39]);
+	MONT_MAC(t0, t1, t2, u[2], m[38]);
+	MONT_MAC(v0, v1, v2, u[3], m[37]);
+	MONT_MAC(w0, w1, w2, u[4], m[36]);
+	MONT_MAC(t0, t1, t2, u[5], m[35]);
+	MONT_MAC(v0, v1, v2, u[6], m[34]);
+	MONT_MAC(w0, w1, w2, u[7], m[33]);
+	MONT_MAC(t0, t1, t2, u[8], m[32]);
+	MONT_MAC(v0, v1, v2, u[9], m[31]);
+	MONT_MAC(w0, w1, w2, u[10], m[30]);
+	MONT_MAC(t0, t1, t2, u[11], m[29]);
+	MONT_MAC(v0, v1, v2, u[12], m[28]);
+	MONT_MAC(w0, w1, w2, u[13], m[27]);
+	MONT_MAC(t0, t1, t2, u[14], m[26]);
+	MONT_MAC(v0, v1, v2, u[15], m[25]);
+	MONT_MAC(w0, w1, w2, u[16], m[24]);
+	MONT_MAC(t0, t1, t2, u[17], m[23]);
+	MONT_MAC(v0, v1, v2, u[18], m[22]);
+	MONT_MAC(w0, w1, w2, u[19], m[21]);
+	MONT_MAC(t0, t1, t2, u[20], m[20]);
+	MONT_MAC(v0, v1, v2, u[21], m[19]);
+	MONT_MAC(w0, w1, w2, u[22], m[18]);
+	MONT_MAC(t0, t1, t2, u[23], m[17]);
+	MONT_MAC(v0, v1, v2, u[24], m[16]);
+	MONT_MAC(w0, w1, w2, u[25], m[15]);
+	MONT_MAC(t0, t1, t2, u[26], m[14]);
+	MONT_MAC(v0, v1, v2, u[27], m[13]);
+	MONT_MAC(w0, w1, w2, u[28], m[12]);
+	MONT_MAC(t0, t1, t2, u[29], m[11]);
+	MONT_MAC(v0, v1, v2, u[30], m[10]);
+	MONT_MAC(w0, w1, w2, u[31], m[9]);
+	MONT_MAC(t0, t1, t2, u[32], m[8]);
+	MONT_MAC(v0, v1, v2, u[33], m[7]);
+	MONT_MAC(w0, w1, w2, u[34], m[6]);
+	MONT_MAC(t0, t1, t2, u[35], m[5]);
+	MONT_MAC(v0, v1, v2, u[36], m[4]);
+	MONT_MAC(w0, w1, w2, u[37], m[3]);
+	MONT_MAC(t0, t1, t2, u[38], m[2]);
+	MONT_MAC(v0, v1, v2, u[39], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[40] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[40], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 41 */
+	MONT_MUL(s0, s1, s2, a[0], a[41]);
+	MONT_MUL(c0, c1, c2, a[1], a[40]);
+	MONT_MAC(s0, s1, s2, a[2], a[39]);
+	MONT_MAC(c0, c1, c2, a[3], a[38]);
+	MONT_MAC(s0, s1, s2, a[4], a[37]);
+	MONT_MAC(c0, c1, c2, a[5], a[36]);
+	MONT_MAC(s0, s1, s2, a[6], a[35]);
+	MONT_MAC(c0, c1, c2, a[7], a[34]);
+	MONT_MAC(s0, s1, s2, a[8], a[33]);
+	MONT_MAC(c0, c1, c2, a[9], a[32]);
+	MONT_MAC(s0, s1, s2, a[10], a[31]);
+	MONT_MAC(c0, c1, c2, a[11], a[30]);
+	MONT_MAC(s0, s1, s2, a[12], a[29]);
+	MONT_MAC(c0, c1, c2, a[13], a[28]);
+	MONT_MAC(s0, s1, s2, a[14], a[27]);
+	MONT_MAC(c0, c1, c2, a[15], a[26]);
+	MONT_MAC(s0, s1, s2, a[16], a[25]);
+	MONT_MAC(c0, c1, c2, a[17], a[24]);
+	MONT_MAC(s0, s1, s2, a[18], a[23]);
+	MONT_MAC(c0, c1, c2, a[19], a[22]);
+	MONT_MAC(s0, s1, s2, a[20], a[21]);
+	MONT_MAC(t0, t1, t2, u[0], m[41]);
+	MONT_MUL(v0, v1, v2, u[1], m[40]);
+	MONT_MUL(w0, w1, w2, u[2], m[39]);
+	MONT_MAC(t0, t1, t2, u[3], m[38]);
+	MONT_MAC(v0, v1, v2, u[4], m[37]);
+	MONT_MAC(w0, w1, w2, u[5], m[36]);
+	MONT_MAC(t0, t1, t2, u[6], m[35]);
+	MONT_MAC(v0, v1, v2, u[7], m[34]);
+	MONT_MAC(w0, w1, w2, u[8], m[33]);
+	MONT_MAC(t0, t1, t2, u[9], m[32]);
+	MONT_MAC(v0, v1, v2, u[10], m[31]);
+	MONT_MAC(w0, w1, w2, u[11], m[30]);
+	MONT_MAC(t0, t1, t2, u[12], m[29]);
+	MONT_MAC(v0, v1, v2, u[13], m[28]);
+	MONT_MAC(w0, w1, w2, u[14], m[27]);
+	MONT_MAC(t0, t1, t2, u[15], m[26]);
+	MONT_MAC(v0, v1, v2, u[16], m[25]);
+	MONT_MAC(w0, w1, w2, u[17], m[24]);
+	MONT_MAC(t0, t1, t2, u[18], m[23]);
+	MONT_MAC(v0, v1, v2, u[19], m[22]);
+	MONT_MAC(w0, w1, w2, u[20], m[21]);
+	MONT_MAC(t0, t1, t2, u[21], m[20]);
+	MONT_MAC(v0, v1, v2, u[22], m[19]);
+	MONT_MAC(w0, w1, w2, u[23], m[18]);
+	MONT_MAC(t0, t1, t2, u[24], m[17]);
+	MONT_MAC(v0, v1, v2, u[25], m[16]);
+	MONT_MAC(w0, w1, w2, u[26], m[15]);
+	MONT_MAC(t0, t1, t2, u[27], m[14]);
+	MONT_MAC(v0, v1, v2, u[28], m[13]);
+	MONT_MAC(w0, w1, w2, u[29], m[12]);
+	MONT_MAC(t0, t1, t2, u[30], m[11]);
+	MONT_MAC(v0, v1, v2, u[31], m[10]);
+	MONT_MAC(w0, w1, w2, u[32], m[9]);
+	MONT_MAC(t0, t1, t2, u[33], m[8]);
+	MONT_MAC(v0, v1, v2, u[34], m[7]);
+	MONT_MAC(w0, w1, w2, u[35], m[6]);
+	MONT_MAC(t0, t1, t2, u[36], m[5]);
+	MONT_MAC(v0, v1, v2, u[37], m[4]);
+	MONT_MAC(w0, w1, w2, u[38], m[3]);
+	MONT_MAC(t0, t1, t2, u[39], m[2]);
+	MONT_MAC(v0, v1, v2, u[40], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[41] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[41], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 42 */
+	MONT_MUL(s0, s1, s2, a[0], a[42]);
+	MONT_MUL(c0, c1, c2, a[1], a[41]);
+	MONT_MAC(s0, s1, s2, a[2], a[40]);
+	MONT_MAC(c0, c1, c2, a[3], a[39]);
+	MONT_MAC(s0, s1, s2, a[4], a[38]);
+	MONT_MAC(c0, c1, c2, a[5], a[37]);
+	MONT_MAC(s0, s1, s2, a[6], a[36]);
+	MONT_MAC(c0, c1, c2, a[7], a[35]);
+	MONT_MAC(s0, s1, s2, a[8], a[34]);
+	MONT_MAC(c0, c1, c2, a[9], a[33]);
+	MONT_MAC(s0, s1, s2, a[10], a[32]);
+	MONT_MAC(c0, c1, c2, a[11], a[31]);
+	MONT_MAC(s0, s1, s2, a[12], a[30]);
+	MONT_MAC(c0, c1, c2, a[13], a[29]);
+	MONT_MAC(s0, s1, s2, a[14], a[28]);
+	MONT_MAC(c0, c1, c2, a[15], a[27]);
+	MONT_MAC(s0, s1, s2, a[16], a[26]);
+	MONT_MAC(c0, c1, c2, a[17], a[25]);
+	MONT_MAC(s0, s1, s2, a[18], a[24]);
+	MONT_MAC(c0, c1, c2, a[19], a[23]);
+	MONT_MAC(s0, s1, s2, a[20], a[22]);
+	MONT_MAC(t0, t1, t2, a[21], a[21]);
+	MONT_MUL(v0, v1, v2, u[0], m[42]);
+	MONT_MUL(w0, w1, w2, u[1], m[41]);
+	MONT_MAC(t0, t1, t2, u[2], m[40]);
+	MONT_MAC(v0, v1, v2, u[3], m[39]);
+	MONT_MAC(w0, w1, w2, u[4], m[38]);
+	MONT_MAC(t0, t1, t2, u[5], m[37]);
+	MONT_MAC(v0, v1, v2, u[6], m[36]);
+	MONT_MAC(w0, w1, w2, u[7], m[35]);
+	MONT_MAC(t0, t1, t2, u[8], m[34]);
+	MONT_MAC(v0, v1, v2, u[9], m[33]);
+	MONT_MAC(w0, w1, w2, u[10], m[32]);
+	MONT_MAC(t0, t1, t2, u[11], m[31]);
+	MONT_MAC(v0, v1, v2, u[12], m[30]);
+	MONT_MAC(w0, w1, w2, u[13], m[29]);
+	MONT_MAC(t0, t1, t2, u[14], m[28]);
+	MONT_MAC(v0, v1, v2, u[15], m[27]);
+	MONT_MAC(w0, w1, w2, u[16], m[26]);
+	MONT_MAC(t0, t1, t2, u[17], m[25]);
+	MONT_MAC(v0, v1, v2, u[18], m[24]);
+	MONT_MAC(w0, w1, w2, u[19], m[23]);
+	MONT_MAC(t0, t1, t2, u[20], m[22]);
+	MONT_MAC(v0, v1, v2, u[21], m[21]);
+	MONT_MAC(w0, w1, w2, u[22], m[20]);
+	MONT_MAC(t0, t1, t2, u[23], m[19]);
+	MONT_MAC(v0, v1, v2, u[24], m[18]);
+	MONT_MAC(w0, w1, w2, u[25], m[17]);
+	MONT_MAC(t0, t1, t2, u[26], m[16]);
+	MONT_MAC(v0, v1, v2, u[27], m[15]);
+	MONT_MAC(w0, w1, w2, u[28], m[14]);
+	MONT_MAC(t0, t1, t2, u[29], m[13]);
+	MONT_MAC(v0, v1, v2, u[30], m[12]);
+	MONT_MAC(w0, w1, w2, u[31], m[11]);
+	MONT_MAC(t0, t1, t2, u[32], m[10]);
+	MONT_MAC(v0, v1, v2, u[33], m[9]);
+	MONT_MAC(w0, w1, w2, u[34], m[8]);
+	MONT_MAC(t0, t1, t2, u[35], m[7]);
+	MONT_MAC(v0, v1, v2, u[36], m[6]);
+	MONT_MAC(w0, w1, w2, u[37], m[5]);
+	MONT_MAC(t0, t1, t2, u[38], m[4]);
+	MONT_MAC(v0, v1, v2, u[39], m[3]);
+	MONT_MAC(w0, w1, w2, u[40], m[2]);
+	MONT_MAC(t0, t1, t2, u[41], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[42] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[42], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 43 */
+	MONT_MUL(s0, s1, s2, a[0], a[43]);
+	MONT_MUL(c0, c1, c2, a[1], a[42]);
+	MONT_MAC(s0, s1, s2, a[2], a[41]);
+	MONT_MAC(c0, c1, c2, a[3], a[40]);
+	MONT_MAC(s0, s1, s2, a[4], a[39]);
+	MONT_MAC(c0, c1, c2, a[5], a[38]);
+	MONT_MAC(s0, s1, s2, a[6], a[37]);
+	MONT_MAC(c0, c1, c2, a[7], a[36]);
+	MONT_MAC(s0, s1, s2, a[8], a[35]);
+	MONT_MAC(c0, c1, c2, a[9], a[34]);
+	MONT_MAC(s0, s1, s2, a[10], a[33]);
+	MONT_MAC(c0, c1, c2, a[11], a[32]);
+	MONT_MAC(s0, s1, s2, a[12], a[31]);
+	MONT_MAC(c0, c1, c2, a[13], a[30]);
+	MONT_MAC(s0, s1, s2, a[14], a[29]);
+	MONT_MAC(c0, c1, c2, a[15], a[28]);
+	MONT_MAC(s0, s1, s2, a[16], a[27]);
+	MONT_MAC(c0, c1, c2, a[17], a[26]);
+	MONT_MAC(s0, s1, s2, a[18], a[25]);
+	MONT_MAC(c0, c1, c2, a[19], a[24]);
+	MONT_MAC(s0, s1, s2, a[20], a[23]);
+	MONT_MAC(c0, c1, c2, a[21], a[22]);
+	MONT_MAC(t0, t1, t2, u[0], m[43]);
+	MONT_MUL(v0, v1, v2, u[1], m[42]);
+	MONT_MUL(w0, w1, w2, u[2], m[41]);
+	MONT_MAC(t0, t1, t2, u[3], m[40]);
+	MONT_MAC(v0, v1, v2, u[4], m[39]);
+	MONT_MAC(w0, w1, w2, u[5], m[38]);
+	MONT_MAC(t0, t1, t2, u[6], m[37]);
+	MONT_MAC(v0, v1, v2, u[7], m[36]);
+	MONT_MAC(w0, w1, w2, u[8], m[35]);
+	MONT_MAC(t0, t1, t2, u[9], m[34]);
+	MONT_MAC(v0, v1, v2, u[10], m[33]);
+	MONT_MAC(w0, w1, w2, u[11], m[32]);
+	MONT_MAC(t0, t1, t2, u[12], m[31]);
+	MONT_MAC(v0, v1, v2, u[13], m[30]);
+	MONT_MAC(w0, w1, w2, u[14], m[29]);
+	MONT_MAC(t0, t1, t2, u[15], m[28]);
+	MONT_MAC(v0, v1, v2, u[16], m[27]);
+	MONT_MAC(w0, w1, w2, u[17], m[26]);
+	MONT_MAC(t0, t1, t2, u[18], m[25]);
+	MONT_MAC(v0, v1, v2, u[19], m[24]);
+	MONT_MAC(w0, w1, w2, u[20], m[23]);
+	MONT_MAC(t0, t1, t2, u[21], m[22]);
+	MONT_MAC(v0, v1, v2, u[22], m[21]);
+	MONT_MAC(w0, w1, w2, u[23], m[20]);
+	MONT_MAC(t0, t1, t2, u[24], m[19]);
+	MONT_MAC(v0, v1, v2, u[25], m[18]);
+	MONT_MAC(w0, w1, w2, u[26], m[17]);
+	MONT_MAC(t0, t1, t2, u[27], m[16]);
+	MONT_MAC(v0, v1, v2, u[28], m[15]);
+	MONT_MAC(w0, w1, w2, u[29], m[14]);
+	MONT_MAC(t0, t1, t2, u[30], m[13]);
+	MONT_MAC(v0, v1, v2, u[31], m[12]);
+	MONT_MAC(w0, w1, w2, u[32], m[11]);
+	MONT_MAC(t0, t1, t2, u[33], m[10]);
+	MONT_MAC(v0, v1, v2, u[34], m[9]);
+	MONT_MAC(w0, w1, w2, u[35], m[8]);
+	MONT_MAC(t0, t1, t2, u[36], m[7]);
+	MONT_MAC(v0, v1, v2, u[37], m[6]);
+	MONT_MAC(w0, w1, w2, u[38], m[5]);
+	MONT_MAC(t0, t1, t2, u[39], m[4]);
+	MONT_MAC(v0, v1, v2, u[40], m[3]);
+	MONT_MAC(w0, w1, w2, u[41], m[2]);
+	MONT_MAC(t0, t1, t2, u[42], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[43] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[43], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 44 */
+	MONT_MUL(s0, s1, s2, a[0], a[44]);
+	MONT_MUL(c0, c1, c2, a[1], a[43]);
+	MONT_MAC(s0, s1, s2, a[2], a[42]);
+	MONT_MAC(c0, c1, c2, a[3], a[41]);
+	MONT_MAC(s0, s1, s2, a[4], a[40]);
+	MONT_MAC(c0, c1, c2, a[5], a[39]);
+	MONT_MAC(s0, s1, s2, a[6], a[38]);
+	MONT_MAC(c0, c1, c2, a[7], a[37]);
+	MONT_MAC(s0, s1, s2, a[8], a[36]);
+	MONT_MAC(c0, c1, c2, a[9], a[35]);
+	MONT_MAC(s0, s1, s2, a[10], a[34]);
+	MONT_MAC(c0, c1, c2, a[11], a[33]);
+	MONT_MAC(s0, s1, s2, a[12], a[32]);
+	MONT_MAC(c0, c1, c2, a[13], a[31]);
+	MONT_MAC(s0, s1, s2, a[14], a[30]);
+	MONT_MAC(c0, c1, c2, a[15], a[29]);
+	MONT_MAC(s0, s1, s2, a[16], a[28]);
+	MONT_MAC(c0, c1, c2, a[17], a[27]);
+	MONT_MAC(s0, s1, s2, a[18], a[26]);
+	MONT_MAC(c0, c1, c2, a[19], a[25]);
+	MONT_MAC(s0, s1, s2, a[20], a[24]);
+	MONT_MAC(c0, c1, c2, a[21], a[23]);
+	MONT_MAC(t0, t1, t2, a[22], a[22]);
+	MONT_MUL(v0, v1, v2, u[0], m[44]);
+	MONT_MUL(w0, w1, w2, u[1], m[43]);
+	MONT_MAC(t0, t1, t2, u[2], m[42]);
+	MONT_MAC(v0, v1, v2, u[3], m[41]);
+	MONT_MAC(w0, w1, w2, u[4], m[40]);
+	MONT_MAC(t0, t1, t2, u[5], m[39]);
+	MONT_MAC(v0, v1, v2, u[6], m[38]);
+	MONT_MAC(w0, w1, w2, u[7], m[37]);
+	MONT_MAC(t0, t1, t2, u[8], m[36]);
+	MONT_MAC(v0, v1, v2, u[9], m[35]);
+	MONT_MAC(w0, w1, w2, u[10], m[34]);
+	MONT_MAC(t0, t1, t2, u[11], m[33]);
+	MONT_MAC(v0, v1, v2, u[12], m[32]);
+	MONT_MAC(w0, w1, w2, u[13], m[31]);
+	MONT_MAC(t0, t1, t2, u[14], m[30]);
+	MONT_MAC(v0, v1, v2, u[15], m[29]);
+	MONT_MAC(w0, w1, w2, u[16], m[28]);
+	MONT_MAC(t0, t1, t2, u[17], m[27]);
+	MONT_MAC(v0, v1, v2, u[18], m[26]);
+	MONT_MAC(w0, w1, w2, u[19], m[25]);
+	MONT_MAC(t0, t1, t2, u[20], m[24]);
+	MONT_MAC(v0, v1, v2, u[21], m[23]);
+	MONT_MAC(w0, w1, w2, u[22], m[22]);
+	MONT_MAC(t0, t1, t2, u[23], m[21]);
+	MONT_MAC(v0, v1, v2, u[24], m[20]);
+	MONT_MAC(w0, w1, w2, u[25], m[19]);
+	MONT_MAC(t0, t1, t2, u[26], m[18]);
+	MONT_MAC(v0, v1, v2, u[27], m[17]);
+	MONT_MAC(w0, w1, w2, u[28], m[16]);
+	MONT_MAC(t0, t1, t2, u[29], m[15]);
+	MONT_MAC(v0, v1, v2, u[30], m[14]);
+	MONT_MAC(w0, w1, w2, u[31], m[13]);
+	MONT_MAC(t0, t1, t2, u[32], m[12]);
+	MONT_MAC(v0, v1, v2, u[33], m[11]);
+	MONT_MAC(w0, w1, w2, u[34], m[10]);
+	MONT_MAC(t0, t1, t2, u[35], m[9]);
+	MONT_MAC(v0, v1, v2, u[36], m[8]);
+	MONT_MAC(w0, w1, w2, u[37], m[7]);
+	MONT_MAC(t0, t1, t2, u[38], m[6]);
+	MONT_MAC(v0, v1, v2, u[39], m[5]);
+	MONT_MAC(w0, w1, w2, u[40], m[4]);
+	MONT_MAC(t0, t1, t2, u[41], m[3]);
+	MONT_MAC(v0, v1, v2, u[42], m[2]);
+	MONT_MAC(w0, w1, w2, u[43], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[44] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[44], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 45 */
+	MONT_MUL(s0, s1, s2, a[0], a[45]);
+	MONT_MUL(c0, c1, c2, a[1], a[44]);
+	MONT_MAC(s0, s1, s2, a[2], a[43]);
+	MONT_MAC(c0, c1, c2, a[3], a[42]);
+	MONT_MAC(s0, s1, s2, a[4], a[41]);
+	MONT_MAC(c0, c1, c2, a[5], a[40]);
+	MONT_MAC(s0, s1, s2, a[6], a[39]);
+	MONT_MAC(c0, c1, c2, a[7], a[38]);
+	MONT_MAC(s0, s1, s2, a[8], a[37]);
+	MONT_MAC(c0, c1, c2, a[9], a[36]);
+	MONT_MAC(s0, s1, s2, a[10], a[35]);
+	MONT_MAC(c0, c1, c2, a[11], a[34]);
+	MONT_MAC(s0, s1, s2, a[12], a[33]);
+	MONT_MAC(c0, c1, c2, a[13], a[32]);
+	MONT_MAC(s0, s1, s2, a[14], a[31]);
+	MONT_MAC(c0, c1, c2, a[15], a[30]);
+	MONT_MAC(s0, s1, s2, a[16], a[29]);
+	MONT_MAC(c0, c1, c2, a[17], a[28]);
+	MONT_MAC(s0, s1, s2, a[18], a[27]);
+	MONT_MAC(c0, c1, c2, a[19], a[26]);
+	MONT_MAC(s0, s1, s2, a[20], a[25]);
+	MONT_MAC(c0, c1, c2, a[21], a[24]);
+	MONT_MAC(s0, s1, s2, a[22], a[23]);
+	MONT_MAC(t0, t1, t2, u[0], m[45]);
+	MONT_MUL(v0, v1, v2, u[1], m[44]);
+	MONT_MUL(w0, w1, w2, u[2], m[43]);
+	MONT_MAC(t0, t1, t2, u[3], m[42]);
+	MONT_MAC(v0, v1, v2, u[4], m[41]);
+	MONT_MAC(w0, w1, w2, u[5], m[40]);
+	MONT_MAC(t0, t1, t2, u[6], m[39]);
+	MONT_MAC(v0, v1, v2, u[7], m[38]);
+	MONT_MAC(w0, w1, w2, u[8], m[37]);
+	MONT_MAC(t0, t1, t2, u[9], m[36]);
+	MONT_MAC(v0, v1, v2, u[10], m[35]);
+	MONT_MAC(w0, w1, w2, u[11], m[34]);
+	MONT_MAC(t0, t1, t2, u[12], m[33]);
+	MONT_MAC(v0, v1, v2, u[13], m[32]);
+	MONT_MAC(w0, w1, w2, u[14], m[31]);
+	MONT_MAC(t0, t1, t2, u[15], m[30]);
+	MONT_MAC(v0, v1, v2, u[16], m[29]);
+	MONT_MAC(w0, w1, w2, u[17], m[28]);
+	MONT_MAC(t0, t1, t2, u[18], m[27]);
+	MONT_MAC(v0, v1, v2, u[19], m[26]);
+	MONT_MAC(w0, w1, w2, u[20], m[25]);
+	MONT_MAC(t0, t1, t2, u[21], m[24]);
+	MONT_MAC(v0, v1, v2, u[22], m[23]);
+	MONT_MAC(w0, w1, w2, u[23], m[22]);
+	MONT_MAC(t0, t1, t2, u[24], m[21]);
+	MONT_MAC(v0, v1, v2, u[25], m[20]);
+	MONT_MAC(w0, w1, w2, u[26], m[19]);
+	MONT_MAC(t0, t1, t2, u[27], m[18]);
+	MONT_MAC(v0, v1, v2, u[28], m[17]);
+	MONT_MAC(w0, w1, w2, u[29], m[16]);
+	MONT_MAC(t0, t1, t2, u[30], m[15]);
+	MONT_MAC(v0, v1, v2, u[31], m[14]);
+	MONT_MAC(w0, w1, w2, u[32], m[13]);
+	MONT_MAC(t0, t1, t2, u[33], m[12]);
+	MONT_MAC(v0, v1, v2, u[34], m[11]);
+	MONT_MAC(w0, w1, w2, u[35], m[10]);
+	MONT_MAC(t0, t1, t2, u[36], m[9]);
+	MONT_MAC(v0, v1, v2, u[37], m[8]);
+	MONT_MAC(w0, w1, w2, u[38], m[7]);
+	MONT_MAC(t0, t1, t2, u[39], m[6]);
+	MONT_MAC(v0, v1, v2, u[40], m[5]);
+	MONT_MAC(w0, w1, w2, u[41], m[4]);
+	MONT_MAC(t0, t1, t2, u[42], m[3]);
+	MONT_MAC(v0, v1, v2, u[43], m[2]);
+	MONT_MAC(w0, w1, w2, u[44], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[45] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[45], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 46 */
+	MONT_MUL(s0, s1, s2, a[0], a[46]);
+	MONT_MUL(c0, c1, c2, a[1], a[45]);
+	MONT_MAC(s0, s1, s2, a[2], a[44]);
+	MONT_MAC(c0, c1, c2, a[3], a[43]);
+	MONT_MAC(s0, s1, s2, a[4], a[42]);
+	MONT_MAC(c0, c1, c2, a[5], a[41]);
+	MONT_MAC(s0, s1, s2, a[6], a[40]);
+	MONT_MAC(c0, c1, c2, a[7], a[39]);
+	MONT_MAC(s0, s1, s2, a[8], a[38]);
+	MONT_MAC(c0, c1, c2, a[9], a[37]);
+	MONT_MAC(s0, s1, s2, a[10], a[36]);
+	MONT_MAC(c0, c1, c2, a[11], a[35]);
+	MONT_MAC(s0, s1, s2, a[12], a[34]);
+	MONT_MAC(c0, c1, c2, a[13], a[33]);
+	MONT_MAC(s0, s1, s2, a[14], a[32]);
+	MONT_MAC(c0, c1, c2, a[15], a[31]);
+	MONT_MAC(s0, s1, s2, a[16], a[30]);
+	MONT_MAC(c0, c1, c2, a[17], a[29]);
+	MONT_MAC(s0, s1, s2, a[18], a[28]);
+	MONT_MAC(c0, c1, c2, a[19], a[27]);
+	MONT_MAC(s0, s1, s2, a[20], a[26]);
+	MONT_MAC(c0, c1, c2, a[21], a[25]);
+	MONT_MAC(s0, s1, s2, a[22], a[24]);
+	MONT_MAC(t0, t1, t2, a[23], a[23]);
+	MONT_MUL(v0, v1, v2, u[0], m[46]);
+	MONT_MUL(w0, w1, w2, u[1], m[45]);
+	MONT_MAC(t0, t1, t2, u[2], m[44]);
+	MONT_MAC(v0, v1, v2, u[3], m[43]);
+	MONT_MAC(w0, w1, w2, u[4], m[42]);
+	MONT_MAC(t0, t1, t2, u[5], m[41]);
+	MONT_MAC(v0, v1, v2, u[6], m[40]);
+	MONT_MAC(w0, w1, w2, u[7], m[39]);
+	MONT_MAC(t0, t1, t2, u[8], m[38]);
+	MONT_MAC(v0, v1, v2, u[9], m[37]);
+	MONT_MAC(w0, w1, w2, u[10], m[36]);
+	MONT_MAC(t0, t1, t2, u[11], m[35]);
+	MONT_MAC(v0, v1, v2, u[12], m[34]);
+	MONT_MAC(w0, w1, w2, u[13], m[33]);
+	MONT_MAC(t0, t1, t2, u[14], m[32]);
+	MONT_MAC(v0, v1, v2, u[15], m[31]);
+	MONT_MAC(w0, w1, w2, u[16], m[30]);
+	MONT_MAC(t0, t1, t2, u[17], m[29]);
+	MONT_MAC(v0, v1, v2, u[18], m[28]);
+	MONT_MAC(w0, w1, w2, u[19], m[27]);
+	MONT_MAC(t0, t1, t2, u[20], m[26]);
+	MONT_MAC(v0, v1, v2, u[21], m[25]);
+	MONT_MAC(w0, w1, w2, u[22], m[24]);
+	MONT_MAC(t0, t1, t2, u[23], m[23]);
+	MONT_MAC(v0, v1, v2, u[24], m[22]);
+	MONT_MAC(w0, w1, w2, u[25], m[21]);
+	MONT_MAC(t0, t1, t2, u[26], m[20]);
+	MONT_MAC(v0, v1, v2, u[27], m[19]);
+	MONT_MAC(w0, w1, w2, u[28], m[18]);
+	MONT_MAC(t0, t1, t2, u[29], m[17]);
+	MONT_MAC(v0, v1, v2, u[30], m[16]);
+	MONT_MAC(w0, w1, w2, u[31], m[15]);
+	MONT_MAC(t0, t1, t2, u[32], m[14]);
+	MONT_MAC(v0, v1, v2, u[33], m[13]);
+	MONT_MAC(w0, w1, w2, u[34], m[12]);
+	MONT_MAC(t0, t1, t2, u[35], m[11]);
+	MONT_MAC(v0, v1, v2, u[36], m[10]);
+	MONT_MAC(w0, w1, w2, u[37], m[9]);
+	MONT_MAC(t0, t1, t2, u[38], m[8]);
+	MONT_MAC(v0, v1, v2, u[39], m[7]);
+	MONT_MAC(w0, w1, w2, u[40], m[6]);
+	MONT_MAC(t0, t1, t2, u[41], m[5]);
+	MONT_MAC(v0, v1, v2, u[42], m[4]);
+	MONT_MAC(w0, w1, w2, u[43], m[3]);
+	MONT_MAC(t0, t1, t2, u[44], m[2]);
+	MONT_MAC(v0, v1, v2, u[45], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[46] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[46], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 47 */
+	MONT_MUL(s0, s1, s2, a[0], a[47]);
+	MONT_MUL(c0, c1, c2, a[1], a[46]);
+	MONT_MAC(s0, s1, s2, a[2], a[45]);
+	MONT_MAC(c0, c1, c2, a[3], a[44]);
+	MONT_MAC(s0, s1, s2, a[4], a[43]);
+	MONT_MAC(c0, c1, c2, a[5], a[42]);
+	MONT_MAC(s0, s1, s2, a[6], a[41]);
+	MONT_MAC(c0, c1, c2, a[7], a[40]);
+	MONT_MAC(s0, s1, s2, a[8], a[39]);
+	MONT_MAC(c0, c1, c2, a[9], a[38]);
+	MONT_MAC(s0, s1, s2, a[10], a[37]);
+	MONT_MAC(c0, c1, c2, a[11], a[36]);
+	MONT_MAC(s0, s1, s2, a[12], a[35]);
+	MONT_MAC(c0, c1, c2, a[13], a[34]);
+	MONT_MAC(s0, s1, s2, a[14], a[33]);
+	MONT_MAC(c0, c1, c2, a[15], a[32]);
+	MONT_MAC(s0, s1, s2, a[16], a[31]);
+	MONT_MAC(c0, c1, c2, a[17], a[30]);
+	MONT_MAC(s0, s1, s2, a[18], a[29]);
+	MONT_MAC(c0, c1, c2, a[19], a[28]);
+	MONT_MAC(s0, s1, s2, a[20], a[27]);
+	MONT_MAC(c0, c1, c2, a[21], a[26]);
+	MONT_MAC(s0, s1, s2, a[22], a[25]);
+	MONT_MAC(c0, c1, c2, a[23], a[24]);
+	MONT_MAC(t0, t1, t2, u[0], m[47]);
+	MONT_MUL(v0, v1, v2, u[1], m[46]);
+	MONT_MUL(w0, w1, w2, u[2], m[45]);
+	MONT_MAC(t0, t1, t2, u[3], m[44]);
+	MONT_MAC(v0, v1, v2, u[4], m[43]);
+	MONT_MAC(w0, w1, w2, u[5], m[42]);
+	MONT_MAC(t0, t1, t2, u[6], m[41]);
+	MONT_MAC(v0, v1, v2, u[7], m[40]);
+	MONT_MAC(w0, w1, w2, u[8], m[39]);
+	MONT_MAC(t0, t1, t2, u[9], m[38]);
+	MONT_MAC(v0, v1, v2, u[10], m[37]);
+	MONT_MAC(w0, w1, w2, u[11], m[36]);
+	MONT_MAC(t0, t1, t2, u[12], m[35]);
+	MONT_MAC(v0, v1, v2, u[13], m[34]);
+	MONT_MAC(w0, w1, w2, u[14], m[33]);
+	MONT_MAC(t0, t1, t2, u[15], m[32]);
+	MONT_MAC(v0, v1, v2, u[16], m[31]);
+	MONT_MAC(w0, w1, w2, u[17], m[30]);
+	MONT_MAC(t0, t1, t2, u[18], m[29]);
+	MONT_MAC(v0, v1, v2, u[19], m[28]);
+	MONT_MAC(w0, w1, w2, u[20], m[27]);
+	MONT_MAC(t0, t1, t2, u[21], m[26]);
+	MONT_MAC(v0, v1, v2, u[22], m[25]);
+	MONT_MAC(w0, w1, w2, u[23], m[24]);
+	MONT_MAC(t0, t1, t2, u[24], m[23]);
+	MONT_MAC(v0, v1, v2, u[25], m[22]);
+	MONT_MAC(w0, w1, w2, u[26], m[21]);
+	MONT_MAC(t0, t1, t2, u[27], m[20]);
+	MONT_MAC(v0, v1, v2, u[28], m[19]);
+	MONT_MAC(w0, w1, w2, u[29], m[18]);
+	MONT_MAC(t0, t1, t2, u[30], m[17]);
+	MONT_MAC(v0, v1, v2, u[31], m[16]);
+	MONT_MAC(w0, w1, w2, u[32], m[15]);
+	MONT_MAC(t0, t1, t2, u[33], m[14]);
+	MONT_MAC(v0, v1, v2, u[34], m[13]);
+	MONT_MAC(w0, w1, w2, u[35], m[12]);
+	MONT_MAC(t0, t1, t2, u[36], m[11]);
+	MONT_MAC(v0, v1, v2, u[37], m[10]);
+	MONT_MAC(w0, w1, w2, u[38], m[9]);
+	MONT_MAC(t0, t1, t2, u[39], m[8]);
+	MONT_MAC(v0, v1, v2, u[40], m[7]);
+	MONT_MAC(w0, w1, w2, u[41], m[6]);
+	MONT_MAC(t0, t1, t2, u[42], m[5]);
+	MONT_MAC(v0, v1, v2, u[43], m[4]);
+	MONT_MAC(w0, w1, w2, u[44], m[3]);
+	MONT_MAC(t0, t1, t2, u[45], m[2]);
+	MONT_MAC(v0, v1, v2, u[46], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	u[47] = t0 * n0;
+	MONT_MAC(t0, t1, t2, u[47], m[0]);
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 48 */
+	MONT_MUL(s0, s1, s2, a[1], a[47]);
+	MONT_MUL(c0, c1, c2, a[2], a[46]);
+	MONT_MAC(s0, s1, s2, a[3], a[45]);
+	MONT_MAC(c0, c1, c2, a[4], a[44]);
+	MONT_MAC(s0, s1, s2, a[5], a[43]);
+	MONT_MAC(c0, c1, c2, a[6], a[42]);
+	MONT_MAC(s0, s1, s2, a[7], a[41]);
+	MONT_MAC(c0, c1, c2, a[8], a[40]);
+	MONT_MAC(s0, s1, s2, a[9], a[39]);
+	MONT_MAC(c0, c1, c2, a[10], a[38]);
+	MONT_MAC(s0, s1, s2, a[11], a[37]);
+	MONT_MAC(c0, c1, c2, a[12], a[36]);
+	MONT_MAC(s0, s1, s2, a[13], a[35]);
+	MONT_MAC(c0, c1, c2, a[14], a[34]);
+	MONT_MAC(s0, s1, s2, a[15], a[33]);
+	MONT_MAC(c0, c1, c2, a[16], a[32]);
+	MONT_MAC(s0, s1, s2, a[17], a[31]);
+	MONT_MAC(c0, c1, c2, a[18], a[30]);
+	MONT_MAC(s0, s1, s2, a[19], a[29]);
+	MONT_MAC(c0, c1, c2, a[20], a[28]);
+	MONT_MAC(s0, s1, s2, a[21], a[27]);
+	MONT_MAC(c0, c1, c2, a[22], a[26]);
+	MONT_MAC(s0, s1, s2, a[23], a[25]);
+	MONT_MAC(t0, t1, t2, a[24], a[24]);
+	MONT_MUL(v0, v1, v2, u[1], m[47]);
+	MONT_MUL(w0, w1, w2, u[2], m[46]);
+	MONT_MAC(t0, t1, t2, u[3], m[45]);
+	MONT_MAC(v0, v1, v2, u[4], m[44]);
+	MONT_MAC(w0, w1, w2, u[5], m[43]);
+	MONT_MAC(t0, t1, t2, u[6], m[42]);
+	MONT_MAC(v0, v1, v2, u[7], m[41]);
+	MONT_MAC(w0, w1, w2, u[8], m[40]);
+	MONT_MAC(t0, t1, t2, u[9], m[39]);
+	MONT_MAC(v0, v1, v2, u[10], m[38]);
+	MONT_MAC(w0, w1, w2, u[11], m[37]);
+	MONT_MAC(t0, t1, t2, u[12], m[36]);
+	MONT_MAC(v0, v1, v2, u[13], m[35]);
+	MONT_MAC(w0, w1, w2, u[14], m[34]);
+	MONT_MAC(t0, t1, t2, u[15], m[33]);
+	MONT_MAC(v0, v1, v2, u[16], m[32]);
+	MONT_MAC(w0, w1, w2, u[17], m[31]);
+	MONT_MAC(t0, t1, t2, u[18], m[30]);
+	MONT_MAC(v0, v1, v2, u[19], m[29]);
+	MONT_MAC(w0, w1, w2, u[20], m[28]);
+	MONT_MAC(t0, t1, t2, u[21], m[27]);
+	MONT_MAC(v0, v1, v2, u[22], m[26]);
+	MONT_MAC(w0, w1, w2, u[23], m[25]);
+	MONT_MAC(t0, t1, t2, u[24], m[24]);
+	MONT_MAC(v0, v1, v2, u[25], m[23]);
+	MONT_MAC(w0, w1, w2, u[26], m[22]);
+	MONT_MAC(t0, t1, t2, u[27], m[21]);
+	MONT_MAC(v0, v1, v2, u[28], m[20]);
+	MONT_MAC(w0, w1, w2, u[29], m[19]);
+	MONT_MAC(t0, t1, t2, u[30], m[18]);
+	MONT_MAC(v0, v1, v2, u[31], m[17]);
+	MONT_MAC(w0, w1, w2, u[32], m[16]);
+	MONT_MAC(t0, t1, t2, u[33], m[15]);
+	MONT_MAC(v0, v1, v2, u[34], m[14]);
+	MONT_MAC(w0, w1, w2, u[35], m[13]);
+	MONT_MAC(t0, t1, t2, u[36], m[12]);
+	MONT_MAC(v0, v1, v2, u[37], m[11]);
+	MONT_MAC(w0, w1, w2, u[38], m[10]);
+	MONT_MAC(t0, t1, t2, u[39], m[9]);
+	MONT_MAC(v0, v1, v2, u[40], m[8]);
+	MONT_MAC(w0, w1, w2, u[41], m[7]);
+	MONT_MAC(t0, t1, t2, u[42], m[6]);
+	MONT_MAC(v0, v1, v2, u[43], m[5]);
+	MONT_MAC(w0, w1, w2, u[44], m[4]);
+	MONT_MAC(t0, t1, t2, u[45], m[3]);
+	MONT_MAC(v0, v1, v2, u[46], m[2]);
+	MONT_MAC(w0, w1, w2, u[47], m[1]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[0] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 49 */
+	MONT_MUL(s0, s1, s2, a[2], a[47]);
+	MONT_MUL(c0, c1, c2, a[3], a[46]);
+	MONT_MAC(s0, s1, s2, a[4], a[45]);
+	MONT_MAC(c0, c1, c2, a[5], a[44]);
+	MONT_MAC(s0, s1, s2, a[6], a[43]);
+	MONT_MAC(c0, c1, c2, a[7], a[42]);
+	MONT_MAC(s0, s1, s2, a[8], a[41]);
+	MONT_MAC(c0, c1, c2, a[9], a[40]);
+	MONT_MAC(s0, s1, s2, a[10], a[39]);
+	MONT_MAC(c0, c1, c2, a[11], a[38]);
+	MONT_MAC(s0, s1, s2, a[12], a[37]);
+	MONT_MAC(c0, c1, c2, a[13], a[36]);
+	MONT_MAC(s0, s1, s2, a[14], a[35]);
+	MONT_MAC(c0, c1, c2, a[15], a[34]);
+	MONT_MAC(s0, s1, s2, a[16], a[33]);
+	MONT_MAC(c0, c1, c2, a[17], a[32]);
+	MONT_MAC(s0, s1, s2, a[18], a[31]);
+	MONT_MAC(c0, c1, c2, a[19], a[30]);
+	MONT_MAC(s0, s1, s2, a[20], a[29]);
+	MONT_MAC(c0, c1, c2, a[21], a[28]);
+	MONT_MAC(s0, s1, s2, a[22], a[27]);
+	MONT_MAC(c0, c1, c2, a[23], a[26]);
+	MONT_MAC(s0, s1, s2, a[24], a[25]);
+	MONT_MAC(t0, t1, t2, u[2], m[47]);
+	MONT_MUL(v0, v1, v2, u[3], m[46]);
+	MONT_MUL(w0, w1, w2, u[4], m[45]);
+	MONT_MAC(t0, t1, t2, u[5], m[44]);
+	MONT_MAC(v0, v1, v2, u[6], m[43]);
+	MONT_MAC(w0, w1, w2, u[7], m[42]);
+	MONT_MAC(t0, t1, t2, u[8], m[41]);
+	MONT_MAC(v0, v1, v2, u[9], m[40]);
+	MONT_MAC(w0, w1, w2, u[10], m[39]);
+	MONT_MAC(t0, t1, t2, u[11], m[38]);
+	MONT_MAC(v0, v1, v2, u[12], m[37]);
+	MONT_MAC(w0, w1, w2, u[13], m[36]);
+	MONT_MAC(t0, t1, t2, u[14], m[35]);
+	MONT_MAC(v0, v1, v2, u[15], m[34]);
+	MONT_MAC(w0, w1, w2, u[16], m[33]);
+	MONT_MAC(t0, t1, t2, u[17], m[32]);
+	MONT_MAC(v0, v1, v2, u[18], m[31]);
+	MONT_MAC(w0, w1, w2, u[19], m[30]);
+	MONT_MAC(t0, t1, t2, u[20], m[29]);
+	MONT_MAC(v0, v1, v2, u[21], m[28]);
+	MONT_MAC(w0, w1, w2, u[22], m[27]);
+	MONT_MAC(t0, t1, t2, u[23], m[26]);
+	MONT_MAC(v0, v1, v2, u[24], m[25]);
+	MONT_MAC(w0, w1, w2, u[25], m[24]);
+	MONT_MAC(t0, t1, t2, u[26], m[23]);
+	MONT_MAC(v0, v1, v2, u[27], m[22]);
+	MONT_MAC(w0, w1, w2, u[28], m[21]);
+	MONT_MAC(t0, t1, t2, u[29], m[20]);
+	MONT_MAC(v0, v1, v2, u[30], m[19]);
+	MONT_MAC(w0, w1, w2, u[31], m[18]);
+	MONT_MAC(t0, t1, t2, u[32], m[17]);
+	MONT_MAC(v0, v1, v2, u[33], m[16]);
+	MONT_MAC(w0, w1, w2, u[34], m[15]);
+	MONT_MAC(t0, t1, t2, u[35], m[14]);
+	MONT_MAC(v0, v1, v2, u[36], m[13]);
+	MONT_MAC(w0, w1, w2, u[37], m[12]);
+	MONT_MAC(t0, t1, t2, u[38], m[11]);
+	MONT_MAC(v0, v1, v2, u[39], m[10]);
+	MONT_MAC(w0, w1, w2, u[40], m[9]);
+	MONT_MAC(t0, t1, t2, u[41], m[8]);
+	MONT_MAC(v0, v1, v2, u[42], m[7]);
+	MONT_MAC(w0, w1, w2, u[43], m[6]);
+	MONT_MAC(t0, t1, t2, u[44], m[5]);
+	MONT_MAC(v0, v1, v2, u[45], m[4]);
+	MONT_MAC(w0, w1, w2, u[46], m[3]);
+	MONT_MAC(t0, t1, t2, u[47], m[2]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[1] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 50 */
+	MONT_MUL(s0, s1, s2, a[3], a[47]);
+	MONT_MUL(c0, c1, c2, a[4], a[46]);
+	MONT_MAC(s0, s1, s2, a[5], a[45]);
+	MONT_MAC(c0, c1, c2, a[6], a[44]);
+	MONT_MAC(s0, s1, s2, a[7], a[43]);
+	MONT_MAC(c0, c1, c2, a[8], a[42]);
+	MONT_MAC(s0, s1, s2, a[9], a[41]);
+	MONT_MAC(c0, c1, c2, a[10], a[40]);
+	MONT_MAC(s0, s1, s2, a[11], a[39]);
+	MONT_MAC(c0, c1, c2, a[12], a[38]);
+	MONT_MAC(s0, s1, s2, a[13], a[37]);
+	MONT_MAC(c0, c1, c2, a[14], a[36]);
+	MONT_MAC(s0, s1, s2, a[15], a[35]);
+	MONT_MAC(c0, c1, c2, a[16], a[34]);
+	MONT_MAC(s0, s1, s2, a[17], a[33]);
+	MONT_MAC(c0, c1, c2, a[18], a[32]);
+	MONT_MAC(s0, s1, s2, a[19], a[31]);
+	MONT_MAC(c0, c1, c2, a[20], a[30]);
+	MONT_MAC(s0, s1, s2, a[21], a[29]);
+	MONT_MAC(c0, c1, c2, a[22], a[28]);
+	MONT_MAC(s0, s1, s2, a[23], a[27]);
+	MONT_MAC(c0, c1, c2, a[24], a[26]);
+	MONT_MAC(t0, t1, t2, a[25], a[25]);
+	MONT_MUL(v0, v1, v2, u[3], m[47]);
+	MONT_MUL(w0, w1, w2, u[4], m[46]);
+	MONT_MAC(t0, t1, t2, u[5], m[45]);
+	MONT_MAC(v0, v1, v2, u[6], m[44]);
+	MONT_MAC(w0, w1, w2, u[7], m[43]);
+	MONT_MAC(t0, t1, t2, u[8], m[42]);
+	MONT_MAC(v0, v1, v2, u[9], m[41]);
+	MONT_MAC(w0, w1, w2, u[10], m[40]);
+	MONT_MAC(t0, t1, t2, u[11], m[39]);
+	MONT_MAC(v0, v1, v2, u[12], m[38]);
+	MONT_MAC(w0, w1, w2, u[13], m[37]);
+	MONT_MAC(t0, t1, t2, u[14], m[36]);
+	MONT_MAC(v0, v1, v2, u[15], m[35]);
+	MONT_MAC(w0, w1, w2, u[16], m[34]);
+	MONT_MAC(t0, t1, t2, u[17], m[33]);
+	MONT_MAC(v0, v1, v2, u[18], m[32]);
+	MONT_MAC(w0, w1, w2, u[19], m[31]);
+	MONT_MAC(t0, t1, t2, u[20], m[30]);
+	MONT_MAC(v0, v1, v2, u[21], m[29]);
+	MONT_MAC(w0, w1, w2, u[22], m[28]);
+	MONT_MAC(t0, t1, t2, u[23], m[27]);
+	MONT_MAC(v0, v1, v2, u[24], m[26]);
+	MONT_MAC(w0, w1, w2, u[25], m[25]);
+	MONT_MAC(t0, t1, t2, u[26], m[24]);
+	MONT_MAC(v0, v1, v2, u[27], m[23]);
+	MONT_MAC(w0, w1, w2, u[28], m[22]);
+	MONT_MAC(t0, t1, t2, u[29], m[21]);
+	MONT_MAC(v0, v1, v2, u[30], m[20]);
+	MONT_MAC(w0, w1, w2, u[31], m[19]);
+	MONT_MAC(t0, t1, t2, u[32], m[18]);
+	MONT_MAC(v0, v1, v2, u[33], m[17]);
+	MONT_MAC(w0, w1, w2, u[34], m[16]);
+	MONT_MAC(t0, t1, t2, u[35], m[15]);
+	MONT_MAC(v0, v1, v2, u[36], m[14]);
+	MONT_MAC(w0, w1, w2, u[37], m[13]);
+	MONT_MAC(t0, t1, t2, u[38], m[12]);
+	MONT_MAC(v0, v1, v2, u[39], m[11]);
+	MONT_MAC(w0, w1, w2, u[40], m[10]);
+	MONT_MAC(t0, t1, t2, u[41], m[9]);
+	MONT_MAC(v0, v1, v2, u[42], m[8]);
+	MONT_MAC(w0, w1, w2, u[43], m[7]);
+	MONT_MAC(t0, t1, t2, u[44], m[6]);
+	MONT_MAC(v0, v1, v2, u[45], m[5]);
+	MONT_MAC(w0, w1, w2, u[46], m[4]);
+	MONT_MAC(t0, t1, t2, u[47], m[3]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[2] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 51 */
+	MONT_MUL(s0, s1, s2, a[4], a[47]);
+	MONT_MUL(c0, c1, c2, a[5], a[46]);
+	MONT_MAC(s0, s1, s2, a[6], a[45]);
+	MONT_MAC(c0, c1, c2, a[7], a[44]);
+	MONT_MAC(s0, s1, s2, a[8], a[43]);
+	MONT_MAC(c0, c1, c2, a[9], a[42]);
+	MONT_MAC(s0, s1, s2, a[10], a[41]);
+	MONT_MAC(c0, c1, c2, a[11], a[40]);
+	MONT_MAC(s0, s1, s2, a[12], a[39]);
+	MONT_MAC(c0, c1, c2, a[13], a[38]);
+	MONT_MAC(s0, s1, s2, a[14], a[37]);
+	MONT_MAC(c0, c1, c2, a[15], a[36]);
+	MONT_MAC(s0, s1, s2, a[16], a[35]);
+	MONT_MAC(c0, c1, c2, a[17], a[34]);
+	MONT_MAC(s0, s1, s2, a[18], a[33]);
+	MONT_MAC(c0, c1, c2, a[19], a[32]);
+	MONT_MAC(s0, s1, s2, a[20], a[31]);
+	MONT_MAC(c0, c1, c2, a[21], a[30]);
+	MONT_MAC(s0, s1, s2, a[22], a[29]);
+	MONT_MAC(c0, c1, c2, a[23], a[28]);
+	MONT_MAC(s0, s1, s2, a[24], a[27]);
+	MONT_MAC(c0, c1, c2, a[25], a[26]);
+	MONT_MAC(t0, t1, t2, u[4], m[47]);
+	MONT_MUL(v0, v1, v2, u[5], m[46]);
+	MONT_MUL(w0, w1, w2, u[6], m[45]);
+	MONT_MAC(t0, t1, t2, u[7], m[44]);
+	MONT_MAC(v0, v1, v2, u[8], m[43]);
+	MONT_MAC(w0, w1, w2, u[9], m[42]);
+	MONT_MAC(t0, t1, t2, u[10], m[41]);
+	MONT_MAC(v0, v1, v2, u[11], m[40]);
+	MONT_MAC(w0, w1, w2, u[12], m[39]);
+	MONT_MAC(t0, t1, t2, u[13], m[38]);
+	MONT_MAC(v0, v1, v2, u[14], m[37]);
+	MONT_MAC(w0, w1, w2, u[15], m[36]);
+	MONT_MAC(t0, t1, t2, u[16], m[35]);
+	MONT_MAC(v0, v1, v2, u[17], m[34]);
+	MONT_MAC(w0, w1, w2, u[18], m[33]);
+	MONT_MAC(t0, t1, t2, u[19], m[32]);
+	MONT_MAC(v0, v1, v2, u[20], m[31]);
+	MONT_MAC(w0, w1, w2, u[21], m[30]);
+	MONT_MAC(t0, t1, t2, u[22], m[29]);
+	MONT_MAC(v0, v1, v2, u[23], m[28]);
+	MONT_MAC(w0, w1, w2, u[24], m[27]);
+	MONT_MAC(t0, t1, t2, u[25], m[26]);
+	MONT_MAC(v0, v1, v2, u[26], m[25]);
+	MONT_MAC(w0, w1, w2, u[27], m[24]);
+	MONT_MAC(t0, t1, t2, u[28], m[23]);
+	MONT_MAC(v0, v1, v2, u[29], m[22]);
+	MONT_MAC(w0, w1, w2, u[30], m[21]);
+	MONT_MAC(t0, t1, t2, u[31], m[20]);
+	MONT_MAC(v0, v1, v2, u[32], m[19]);
+	MONT_MAC(w0, w1, w2, u[33], m[18]);
+	MONT_MAC(t0, t1, t2, u[34], m[17]);
+	MONT_MAC(v0, v1, v2, u[35], m[16]);
+	MONT_MAC(w0, w1, w2, u[36], m[15]);
+	MONT_MAC(t0, t1, t2, u[37], m[14]);
+	MONT_MAC(v0, v1, v2, u[38], m[13]);
+	MONT_MAC(w0, w1, w2, u[39], m[12]);
+	MONT_MAC(t0, t1, t2, u[40], m[11]);
+	MONT_MAC(v0, v1, v2, u[41], m[10]);
+	MONT_MAC(w0, w1, w2, u[42], m[9]);
+	MONT_MAC(t0, t1, t2, u[43], m[8]);
+	MONT_MAC(v0, v1, v2, u[44], m[7]);
+	MONT_MAC(w0, w1, w2, u[45], m[6]);
+	MONT_MAC(t0, t1, t2, u[46], m[5]);
+	MONT_MAC(v0, v1, v2, u[47], m[4]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[3] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 52 */
+	MONT_MUL(s0, s1, s2, a[5], a[47]);
+	MONT_MUL(c0, c1, c2, a[6], a[46]);
+	MONT_MAC(s0, s1, s2, a[7], a[45]);
+	MONT_MAC(c0, c1, c2, a[8], a[44]);
+	MONT_MAC(s0, s1, s2, a[9], a[43]);
+	MONT_MAC(c0, c1, c2, a[10], a[42]);
+	MONT_MAC(s0, s1, s2, a[11], a[41]);
+	MONT_MAC(c0, c1, c2, a[12], a[40]);
+	MONT_MAC(s0, s1, s2, a[13], a[39]);
+	MONT_MAC(c0, c1, c2, a[14], a[38]);
+	MONT_MAC(s0, s1, s2, a[15], a[37]);
+	MONT_MAC(c0, c1, c2, a[16], a[36]);
+	MONT_MAC(s0, s1, s2, a[17], a[35]);
+	MONT_MAC(c0, c1, c2, a[18], a[34]);
+	MONT_MAC(s0, s1, s2, a[19], a[33]);
+	MONT_MAC(c0, c1, c2, a[20], a[32]);
+	MONT_MAC(s0, s1, s2, a[21], a[31]);
+	MONT_MAC(c0, c1, c2, a[22], a[30]);
+	MONT_MAC(s0, s1, s2, a[23], a[29]);
+	MONT_MAC(c0, c1, c2, a[24], a[28]);
+	MONT_MAC(s0, s1, s2, a[25], a[27]);
+	MONT_MAC(t0, t1, t2, a[26], a[26]);
+	MONT_MUL(v0, v1, v2, u[5], m[47]);
+	MONT_MUL(w0, w1, w2, u[6], m[46]);
+	MONT_MAC(t0, t1, t2, u[7], m[45]);
+	MONT_MAC(v0, v1, v2, u[8], m[44]);
+	MONT_MAC(w0, w1, w2, u[9], m[43]);
+	MONT_MAC(t0, t1, t2, u[10], m[42]);
+	MONT_MAC(v0, v1, v2, u[11], m[41]);
+	MONT_MAC(w0, w1, w2, u[12], m[40]);
+	MONT_MAC(t0, t1, t2, u[13], m[39]);
+	MONT_MAC(v0, v1, v2, u[14], m[38]);
+	MONT_MAC(w0, w1, w2, u[15], m[37]);
+	MONT_MAC(t0, t1, t2, u[16], m[36]);
+	MONT_MAC(v0, v1, v2, u[17], m[35]);
+	MONT_MAC(w0, w1, w2, u[18], m[34]);
+	MONT_MAC(t0, t1, t2, u[19], m[33]);
+	MONT_MAC(v0, v1, v2, u[20], m[32]);
+	MONT_MAC(w0, w1, w2, u[21], m[31]);
+	MONT_MAC(t0, t1, t2, u[22], m[30]);
+	MONT_MAC(v0, v1, v2, u[23], m[29]);
+	MONT_MAC(w0, w1, w2, u[24], m[28]);
+	MONT_MAC(t0, t1, t2, u[25], m[27]);
+	MONT_MAC(v0, v1, v2, u[26], m[26]);
+	MONT_MAC(w0, w1, w2, u[27], m[25]);
+	MONT_MAC(t0, t1, t2, u[28], m[24]);
+	MONT_MAC(v0, v1, v2, u[29], m[23]);
+	MONT_MAC(w0, w1, w2, u[30], m[22]);
+	MONT_MAC(t0, t1, t2, u[31], m[21]);
+	MONT_MAC(v0, v1, v2, u[32], m[20]);
+	MONT_MAC(w0, w1, w2, u[33], m[19]);
+	MONT_MAC(t0, t1, t2, u[34], m[18]);
+	MONT_MAC(v0, v1, v2, u[35], m[17]);
+	MONT_MAC(w0, w1, w2, u[36], m[16]);
+	MONT_MAC(t0, t1, t2, u[37], m[15]);
+	MONT_MAC(v0, v1, v2, u[38], m[14]);
+	MONT_MAC(w0, w1, w2, u[39], m[13]);
+	MONT_MAC(t0, t1, t2, u[40], m[12]);
+	MONT_MAC(v0, v1, v2, u[41], m[11]);
+	MONT_MAC(w0, w1, w2, u[42], m[10]);
+	MONT_MAC(t0, t1, t2, u[43], m[9]);
+	MONT_MAC(v0, v1, v2, u[44], m[8]);
+	MONT_MAC(w0, w1, w2, u[45], m[7]);
+	MONT_MAC(t0, t1, t2, u[46], m[6]);
+	MONT_MAC(v0, v1, v2, u[47], m[5]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[4] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 53 */
+	MONT_MUL(s0, s1, s2, a[6], a[47]);
+	MONT_MUL(c0, c1, c2, a[7], a[46]);
+	MONT_MAC(s0, s1, s2, a[8], a[45]);
+	MONT_MAC(c0, c1, c2, a[9], a[44]);
+	MONT_MAC(s0, s1, s2, a[10], a[43]);
+	MONT_MAC(c0, c1, c2, a[11], a[42]);
+	MONT_MAC(s0, s1, s2, a[12], a[41]);
+	MONT_MAC(c0, c1, c2, a[13], a[40]);
+	MONT_MAC(s0, s1, s2, a[14], a[39]);
+	MONT_MAC(c0, c1, c2, a[15], a[38]);
+	MONT_MAC(s0, s1, s2, a[16], a[37]);
+	MONT_MAC(c0, c1, c2, a[17], a[36]);
+	MONT_MAC(s0, s1, s2, a[18], a[35]);
+	MONT_MAC(c0, c1, c2, a[19], a[34]);
+	MONT_MAC(s0, s1, s2, a[20], a[33]);
+	MONT_MAC(c0, c1, c2, a[21], a[32]);
+	MONT_MAC(s0, s1, s2, a[22], a[31]);
+	MONT_MAC(c0, c1, c2, a[23], a[30]);
+	MONT_MAC(s0, s1, s2, a[24], a[29]);
+	MONT_MAC(c0, c1, c2, a[25], a[28]);
+	MONT_MAC(s0, s1, s2, a[26], a[27]);
+	MONT_MAC(t0, t1, t2, u[6], m[47]);
+	MONT_MUL(v0, v1, v2, u[7], m[46]);
+	MONT_MUL(w0, w1, w2, u[8], m[45]);
+	MONT_MAC(t0, t1, t2, u[9], m[44]);
+	MONT_MAC(v0, v1, v2, u[10], m[43]);
+	MONT_MAC(w0, w1, w2, u[11], m[42]);
+	MONT_MAC(t0, t1, t2, u[12], m[41]);
+	MONT_MAC(v0, v1, v2, u[13], m[40]);
+	MONT_MAC(w0, w1, w2, u[14], m[39]);
+	MONT_MAC(t0, t1, t2, u[15], m[38]);
+	MONT_MAC(v0, v1, v2, u[16], m[37]);
+	MONT_MAC(w0, w1, w2, u[17], m[36]);
+	MONT_MAC(t0, t1, t2, u[18], m[35]);
+	MONT_MAC(v0, v1, v2, u[19], m[34]);
+	MONT_MAC(w0, w1, w2, u[20], m[33]);
+	MONT_MAC(t0, t1, t2, u[21], m[32]);
+	MONT_MAC(v0, v1, v2, u[22], m[31]);
+	MONT_MAC(w0, w1, w2, u[23], m[30]);
+	MONT_MAC(t0, t1, t2, u[24], m[29]);
+	MONT_MAC(v0, v1, v2, u[25], m[28]);
+	MONT_MAC(w0, w1, w2, u[26], m[27]);
+	MONT_MAC(t0, t1, t2, u[27], m[26]);
+	MONT_MAC(v0, v1, v2, u[28], m[25]);
+	MONT_MAC(w0, w1, w2, u[29], m[24]);
+	MONT_MAC(t0, t1, t2, u[30], m[23]);
+	MONT_MAC(v0, v1, v2, u[31], m[22]);
+	MONT_MAC(w0, w1, w2, u[32], m[21]);
+	MONT_MAC(t0, t1, t2, u[33], m[20]);
+	MONT_MAC(v0, v1, v2, u[34], m[19]);
+	MONT_MAC(w0, w1, w2, u[35], m[18]);
+	MONT_MAC(t0, t1, t2, u[36], m[17]);
+	MONT_MAC(v0, v1, v2, u[37], m[16]);
+	MONT_MAC(w0, w1, w2, u[38], m[15]);
+	MONT_MAC(t0, t1, t2, u[39], m[14]);
+	MONT_MAC(v0, v1, v2, u[40], m[13]);
+	MONT_MAC(w0, w1, w2, u[41], m[12]);
+	MONT_MAC(t0, t1, t2, u[42], m[11]);
+	MONT_MAC(v0, v1, v2, u[43], m[10]);
+	MONT_MAC(w0, w1, w2, u[44], m[9]);
+	MONT_MAC(t0, t1, t2, u[45], m[8]);
+	MONT_MAC(v0, v1, v2, u[46], m[7]);
+	MONT_MAC(w0, w1, w2, u[47], m[6]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[5] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 54 */
+	MONT_MUL(s0, s1, s2, a[7], a[47]);
+	MONT_MUL(c0, c1, c2, a[8], a[46]);
+	MONT_MAC(s0, s1, s2, a[9], a[45]);
+	MONT_MAC(c0, c1, c2, a[10], a[44]);
+	MONT_MAC(s0, s1, s2, a[11], a[43]);
+	MONT_MAC(c0, c1, c2, a[12], a[42]);
+	MONT_MAC(s0, s1, s2, a[13], a[41]);
+	MONT_MAC(c0, c1, c2, a[14], a[40]);
+	MONT_MAC(s0, s1, s2, a[15], a[39]);
+	MONT_MAC(c0, c1, c2, a[16], a[38]);
+	MONT_MAC(s0, s1, s2, a[17], a[37]);
+	MONT_MAC(c0, c1, c2, a[18], a[36]);
+	MONT_MAC(s0, s1, s2, a[19], a[35]);
+	MONT_MAC(c0, c1, c2, a[20], a[34]);
+	MONT_MAC(s0, s1, s2, a[21], a[33]);
+	MONT_MAC(c0, c1, c2, a[22], a[32]);
+	MONT_MAC(s0, s1, s2, a[23], a[31]);
+	MONT_MAC(c0, c1, c2, a[24], a[30]);
+	MONT_MAC(s0, s1, s2, a[25], a[29]);
+	MONT_MAC(c0, c1, c2, a[26], a[28]);
+	MONT_MAC(t0, t1, t2, a[27], a[27]);
+	MONT_MUL(v0, v1, v2, u[7], m[47]);
+	MONT_MUL(w0, w1, w2, u[8], m[46]);
+	MONT_MAC(t0, t1, t2, u[9], m[45]);
+	MONT_MAC(v0, v1, v2, u[10], m[44]);
+	MONT_MAC(w0, w1, w2, u[11], m[43]);
+	MONT_MAC(t0, t1, t2, u[12], m[42]);
+	MONT_MAC(v0, v1, v2, u[13], m[41]);
+	MONT_MAC(w0, w1, w2, u[14], m[40]);
+	MONT_MAC(t0, t1, t2, u[15], m[39]);
+	MONT_MAC(v0, v1, v2, u[16], m[38]);
+	MONT_MAC(w0, w1, w2, u[17], m[37]);
+	MONT_MAC(t0, t1, t2, u[18], m[36]);
+	MONT_MAC(v0, v1, v2, u[19], m[35]);
+	MONT_MAC(w0, w1, w2, u[20], m[34]);
+	MONT_MAC(t0, t1, t2, u[21], m[33]);
+	MONT_MAC(v0, v1, v2, u[22], m[32]);
+	MONT_MAC(w0, w1, w2, u[23], m[31]);
+	MONT_MAC(t0, t1, t2, u[24], m[30]);
+	MONT_MAC(v0, v1, v2, u[25], m[29]);
+	MONT_MAC(w0, w1, w2, u[26], m[28]);
+	MONT_MAC(t0, t1, t2, u[27], m[27]);
+	MONT_MAC(v0, v1, v2, u[28], m[26]);
+	MONT_MAC(w0, w1, w2, u[29], m[25]);
+	MONT_MAC(t0, t1, t2, u[30], m[24]);
+	MONT_MAC(v0, v1, v2, u[31], m[23]);
+	MONT_MAC(w0, w1, w2, u[32], m[22]);
+	MONT_MAC(t0, t1, t2, u[33], m[21]);
+	MONT_MAC(v0, v1, v2, u[34], m[20]);
+	MONT_MAC(w0, w1, w2, u[35], m[19]);
+	MONT_MAC(t0, t1, t2, u[36], m[18]);
+	MONT_MAC(v0, v1, v2, u[37], m[17]);
+	MONT_MAC(w0, w1, w2, u[38], m[16]);
+	MONT_MAC(t0, t1, t2, u[39], m[15]);
+	MONT_MAC(v0, v1, v2, u[40], m[14]);
+	MONT_MAC(w0, w1, w2, u[41], m[13]);
+	MONT_MAC(t0, t1, t2, u[42], m[12]);
+	MONT_MAC(v0, v1, v2, u[43], m[11]);
+	MONT_MAC(w0, w1, w2, u[44], m[10]);
+	MONT_MAC(t0, t1, t2, u[45], m[9]);
+	MONT_MAC(v0, v1, v2, u[46], m[8]);
+	MONT_MAC(w0, w1, w2, u[47], m[7]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[6] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 55 */
+	MONT_MUL(s0, s1, s2, a[8], a[47]);
+	MONT_MUL(c0, c1, c2, a[9], a[46]);
+	MONT_MAC(s0, s1, s2, a[10], a[45]);
+	MONT_MAC(c0, c1, c2, a[11], a[44]);
+	MONT_MAC(s0, s1, s2, a[12], a[43]);
+	MONT_MAC(c0, c1, c2, a[13], a[42]);
+	MONT_MAC(s0, s1, s2, a[14], a[41]);
+	MONT_MAC(c0, c1, c2, a[15], a[40]);
+	MONT_MAC(s0, s1, s2, a[16], a[39]);
+	MONT_MAC(c0, c1, c2, a[17], a[38]);
+	MONT_MAC(s0, s1, s2, a[18], a[37]);
+	MONT_MAC(c0, c1, c2, a[19], a[36]);
+	MONT_MAC(s0, s1, s2, a[20], a[35]);
+	MONT_MAC(c0, c1, c2, a[21], a[34]);
+	MONT_MAC(s0, s1, s2, a[22], a[33]);
+	MONT_MAC(c0, c1, c2, a[23], a[32]);
+	MONT_MAC(s0, s1, s2, a[24], a[31]);
+	MONT_MAC(c0, c1, c2, a[25], a[30]);
+	MONT_MAC(s0, s1, s2, a[26], a[29]);
+	MONT_MAC(c0, c1, c2, a[27], a[28]);
+	MONT_MAC(t0, t1, t2, u[8], m[47]);
+	MONT_MUL(v0, v1, v2, u[9], m[46]);
+	MONT_MUL(w0, w1, w2, u[10], m[45]);
+	MONT_MAC(t0, t1, t2, u[11], m[44]);
+	MONT_MAC(v0, v1, v2, u[12], m[43]);
+	MONT_MAC(w0, w1, w2, u[13], m[42]);
+	MONT_MAC(t0, t1, t2, u[14], m[41]);
+	MONT_MAC(v0, v1, v2, u[15], m[40]);
+	MONT_MAC(w0, w1, w2, u[16], m[39]);
+	MONT_MAC(t0, t1, t2, u[17], m[38]);
+	MONT_MAC(v0, v1, v2, u[18], m[37]);
+	MONT_MAC(w0, w1, w2, u[19], m[36]);
+	MONT_MAC(t0, t1, t2, u[20], m[35]);
+	MONT_MAC(v0, v1, v2, u[21], m[34]);
+	MONT_MAC(w0, w1, w2, u[22], m[33]);
+	MONT_MAC(t0, t1, t2, u[23], m[32]);
+	MONT_MAC(v0, v1, v2, u[24], m[31]);
+	MONT_MAC(w0, w1, w2, u[25], m[30]);
+	MONT_MAC(t0, t1, t2, u[26], m[29]);
+	MONT_MAC(v0, v1, v2, u[27], m[28]);
+	MONT_MAC(w0, w1, w2, u[28], m[27]);
+	MONT_MAC(t0, t1, t2, u[29], m[26]);
+	MONT_MAC(v0, v1, v2, u[30], m[25]);
+	MONT_MAC(w0, w1, w2, u[31], m[24]);
+	MONT_MAC(t0, t1, t2, u[32], m[23]);
+	MONT_MAC(v0, v1, v2, u[33], m[22]);
+	MONT_MAC(w0, w1, w2, u[34], m[21]);
+	MONT_MAC(t0, t1, t2, u[35], m[20]);
+	MONT_MAC(v0, v1, v2, u[36], m[19]);
+	MONT_MAC(w0, w1, w2, u[37], m[18]);
+	MONT_MAC(t0, t1, t2, u[38], m[17]);
+	MONT_MAC(v0, v1, v2, u[39], m[16]);
+	MONT_MAC(w0, w1, w2, u[40], m[15]);
+	MONT_MAC(t0, t1, t2, u[41], m[14]);
+	MONT_MAC(v0, v1, v2, u[42], m[13]);
+	MONT_MAC(w0, w1, w2, u[43], m[12]);
+	MONT_MAC(t0, t1, t2, u[44], m[11]);
+	MONT_MAC(v0, v1, v2, u[45], m[10]);
+	MONT_MAC(w0, w1, w2, u[46], m[9]);
+	MONT_MAC(t0, t1, t2, u[47], m[8]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[7] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 56 */
+	MONT_MUL(s0, s1, s2, a[9], a[47]);
+	MONT_MUL(c0, c1, c2, a[10], a[46]);
+	MONT_MAC(s0, s1, s2, a[11], a[45]);
+	MONT_MAC(c0, c1, c2, a[12], a[44]);
+	MONT_MAC(s0, s1, s2, a[13], a[43]);
+	MONT_MAC(c0, c1, c2, a[14], a[42]);
+	MONT_MAC(s0, s1, s2, a[15], a[41]);
+	MONT_MAC(c0, c1, c2, a[16], a[40]);
+	MONT_MAC(s0, s1, s2, a[17], a[39]);
+	MONT_MAC(c0, c1, c2, a[18], a[38]);
+	MONT_MAC(s0, s1, s2, a[19], a[37]);
+	MONT_MAC(c0, c1, c2, a[20], a[36]);
+	MONT_MAC(s0, s1, s2, a[21], a[35]);
+	MONT_MAC(c0, c1, c2, a[22], a[34]);
+	MONT_MAC(s0, s1, s2, a[23], a[33]);
+	MONT_MAC(c0, c1, c2, a[24], a[32]);
+	MONT_MAC(s0, s1, s2, a[25], a[31]);
+	MONT_MAC(c0, c1, c2, a[26], a[30]);
+	MONT_MAC(s0, s1, s2, a[27], a[29]);
+	MONT_MAC(t0, t1, t2, a[28], a[28]);
+	MONT_MUL(v0, v1, v2, u[9], m[47]);
+	MONT_MUL(w0, w1, w2, u[10], m[46]);
+	MONT_MAC(t0, t1, t2, u[11], m[45]);
+	MONT_MAC(v0, v1, v2, u[12], m[44]);
+	MONT_MAC(w0, w1, w2, u[13], m[43]);
+	MONT_MAC(t0, t1, t2, u[14], m[42]);
+	MONT_MAC(v0, v1, v2, u[15], m[41]);
+	MONT_MAC(w0, w1, w2, u[16], m[40]);
+	MONT_MAC(t0, t1, t2, u[17], m[39]);
+	MONT_MAC(v0, v1, v2, u[18], m[38]);
+	MONT_MAC(w0, w1, w2, u[19], m[37]);
+	MONT_MAC(t0, t1, t2, u[20], m[36]);
+	MONT_MAC(v0, v1, v2, u[21], m[35]);
+	MONT_MAC(w0, w1, w2, u[22], m[34]);
+	MONT_MAC(t0, t1, t2, u[23], m[33]);
+	MONT_MAC(v0, v1, v2, u[24], m[32]);
+	MONT_MAC(w0, w1, w2, u[25], m[31]);
+	MONT_MAC(t0, t1, t2, u[26], m[30]);
+	MONT_MAC(v0, v1, v2, u[27], m[29]);
+	MONT_MAC(w0, w1, w2, u[28], m[28]);
+	MONT_MAC(t0, t1, t2, u[29], m[27]);
+	MONT_MAC(v0, v1, v2, u[30], m[26]);
+	MONT_MAC(w0, w1, w2, u[31], m[25]);
+	MONT_MAC(t0, t1, t2, u[32], m[24]);
+	MONT_MAC(v0, v1, v2, u[33], m[23]);
+	MONT_MAC(w0, w1, w2, u[34], m[22]);
+	MONT_MAC(t0, t1, t2, u[35], m[21]);
+	MONT_MAC(v0, v1, v2, u[36], m[20]);
+	MONT_MAC(w0, w1, w2, u[37], m[19]);
+	MONT_MAC(t0, t1, t2, u[38], m[18]);
+	MONT_MAC(v0, v1, v2, u[39], m[17]);
+	MONT_MAC(w0, w1, w2, u[40], m[16]);
+	MONT_MAC(t0, t1, t2, u[41], m[15]);
+	MONT_MAC(v0, v1, v2, u[42], m[14]);
+	MONT_MAC(w0, w1, w2, u[43], m[13]);
+	MONT_MAC(t0, t1, t2, u[44], m[12]);
+	MONT_MAC(v0, v1, v2, u[45], m[11]);
+	MONT_MAC(w0, w1, w2, u[46], m[10]);
+	MONT_MAC(t0, t1, t2, u[47], m[9]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[8] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 57 */
+	MONT_MUL(s0, s1, s2, a[10], a[47]);
+	MONT_MUL(c0, c1, c2, a[11], a[46]);
+	MONT_MAC(s0, s1, s2, a[12], a[45]);
+	MONT_MAC(c0, c1, c2, a[13], a[44]);
+	MONT_MAC(s0, s1, s2, a[14], a[43]);
+	MONT_MAC(c0, c1, c2, a[15], a[42]);
+	MONT_MAC(s0, s1, s2, a[16], a[41]);
+	MONT_MAC(c0, c1, c2, a[17], a[40]);
+	MONT_MAC(s0, s1, s2, a[18], a[39]);
+	MONT_MAC(c0, c1, c2, a[19], a[38]);
+	MONT_MAC(s0, s1, s2, a[20], a[37]);
+	MONT_MAC(c0, c1, c2, a[21], a[36]);
+	MONT_MAC(s0, s1, s2, a[22], a[35]);
+	MONT_MAC(c0, c1, c2, a[23], a[34]);
+	MONT_MAC(s0, s1, s2, a[24], a[33]);
+	MONT_MAC(c0, c1, c2, a[25], a[32]);
+	MONT_MAC(s0, s1, s2, a[26], a[31]);
+	MONT_MAC(c0, c1, c2, a[27], a[30]);
+	MONT_MAC(s0, s1, s2, a[28], a[29]);
+	MONT_MAC(t0, t1, t2, u[10], m[47]);
+	MONT_MUL(v0, v1, v2, u[11], m[46]);
+	MONT_MUL(w0, w1, w2, u[12], m[45]);
+	MONT_MAC(t0, t1, t2, u[13], m[44]);
+	MONT_MAC(v0, v1, v2, u[14], m[43]);
+	MONT_MAC(w0, w1, w2, u[15], m[42]);
+	MONT_MAC(t0, t1, t2, u[16], m[41]);
+	MONT_MAC(v0, v1, v2, u[17], m[40]);
+	MONT_MAC(w0, w1, w2, u[18], m[39]);
+	MONT_MAC(t0, t1, t2, u[19], m[38]);
+	MONT_MAC(v0, v1, v2, u[20], m[37]);
+	MONT_MAC(w0, w1, w2, u[21], m[36]);
+	MONT_MAC(t0, t1, t2, u[22], m[35]);
+	MONT_MAC(v0, v1, v2, u[23], m[34]);
+	MONT_MAC(w0, w1, w2, u[24], m[33]);
+	MONT_MAC(t0, t1, t2, u[25], m[32]);
+	MONT_MAC(v0, v1, v2, u[26], m[31]);
+	MONT_MAC(w0, w1, w2, u[27], m[30]);
+	MONT_MAC(t0, t1, t2, u[28], m[29]);
+	MONT_MAC(v0, v1, v2, u[29], m[28]);
+	MONT_MAC(w0, w1, w2, u[30], m[27]);
+	MONT_MAC(t0, t1, t2, u[31], m[26]);
+	MONT_MAC(v0, v1, v2, u[32], m[25]);
+	MONT_MAC(w0, w1, w2, u[33], m[24]);
+	MONT_MAC(t0, t1, t2, u[34], m[23]);
+	MONT_MAC(v0, v1, v2, u[35], m[22]);
+	MONT_MAC(w0, w1, w2, u[36], m[21]);
+	MONT_MAC(t0, t1, t2, u[37], m[20]);
+	MONT_MAC(v0, v1, v2, u[38], m[19]);
+	MONT_MAC(w0, w1, w2, u[39], m[18]);
+	MONT_MAC(t0, t1, t2, u[40], m[17]);
+	MONT_MAC(v0, v1, v2, u[41], m[16]);
+	MONT_MAC(w0, w1, w2, u[42], m[15]);
+	MONT_MAC(t0, t1, t2, u[43], m[14]);
+	MONT_MAC(v0, v1, v2, u[44], m[13]);
+	MONT_MAC(w0, w1, w2, u[45], m[12]);
+	MONT_MAC(t0, t1, t2, u[46], m[11]);
+	MONT_MAC(v0, v1, v2, u[47], m[10]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[9] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 58 */
+	MONT_MUL(s0, s1, s2, a[11], a[47]);
+	MONT_MUL(c0, c1, c2, a[12], a[46]);
+	MONT_MAC(s0, s1, s2, a[13], a[45]);
+	MONT_MAC(c0, c1, c2, a[14], a[44]);
+	MONT_MAC(s0, s1, s2, a[15], a[43]);
+	MONT_MAC(c0, c1, c2, a[16], a[42]);
+	MONT_MAC(s0, s1, s2, a[17], a[41]);
+	MONT_MAC(c0, c1, c2, a[18], a[40]);
+	MONT_MAC(s0, s1, s2, a[19], a[39]);
+	MONT_MAC(c0, c1, c2, a[20], a[38]);
+	MONT_MAC(s0, s1, s2, a[21], a[37]);
+	MONT_MAC(c0, c1, c2, a[22], a[36]);
+	MONT_MAC(s0, s1, s2, a[23], a[35]);
+	MONT_MAC(c0, c1, c2, a[24], a[34]);
+	MONT_MAC(s0, s1, s2, a[25], a[33]);
+	MONT_MAC(c0, c1, c2, a[26], a[32]);
+	MONT_MAC(s0, s1, s2, a[27], a[31]);
+	MONT_MAC(c0, c1, c2, a[28], a[30]);
+	MONT_MAC(t0, t1, t2, a[29], a[29]);
+	MONT_MUL(v0, v1, v2, u[11], m[47]);
+	MONT_MUL(w0, w1, w2, u[12], m[46]);
+	MONT_MAC(t0, t1, t2, u[13], m[45]);
+	MONT_MAC(v0, v1, v2, u[14], m[44]);
+	MONT_MAC(w0, w1, w2, u[15], m[43]);
+	MONT_MAC(t0, t1, t2, u[16], m[42]);
+	MONT_MAC(v0, v1, v2, u[17], m[41]);
+	MONT_MAC(w0, w1, w2, u[18], m[40]);
+	MONT_MAC(t0, t1, t2, u[19], m[39]);
+	MONT_MAC(v0, v1, v2, u[20], m[38]);
+	MONT_MAC(w0, w1, w2, u[21], m[37]);
+	MONT_MAC(t0, t1, t2, u[22], m[36]);
+	MONT_MAC(v0, v1, v2, u[23], m[35]);
+	MONT_MAC(w0, w1, w2, u[24], m[34]);
+	MONT_MAC(t0, t1, t2, u[25], m[33]);
+	MONT_MAC(v0, v1, v2, u[26], m[32]);
+	MONT_MAC(w0, w1, w2, u[27], m[31]);
+	MONT_MAC(t0, t1, t2, u[28], m[30]);
+	MONT_MAC(v0, v1, v2, u[29], m[29]);
+	MONT_MAC(w0, w1, w2, u[30], m[28]);
+	MONT_MAC(t0, t1, t2, u[31], m[27]);
+	MONT_MAC(v0, v1, v2, u[32], m[26]);
+	MONT_MAC(w0, w1, w2, u[33], m[25]);
+	MONT_MAC(t0, t1, t2, u[34], m[24]);
+	MONT_MAC(v0, v1, v2, u[35], m[23]);
+	MONT_MAC(w0, w1, w2, u[36], m[22]);
+	MONT_MAC(t0, t1, t2, u[37], m[21]);
+	MONT_MAC(v0, v1, v2, u[38], m[20]);
+	MONT_MAC(w0, w1, w2, u[39], m[19]);
+	MONT_MAC(t0, t1, t2, u[40], m[18]);
+	MONT_MAC(v0, v1, v2, u[41], m[17]);
+	MONT_MAC(w0, w1, w2, u[42], m[16]);
+	MONT_MAC(t0, t1, t2, u[43], m[15]);
+	MONT_MAC(v0, v1, v2, u[44], m[14]);
+	MONT_MAC(w0, w1, w2, u[45], m[13]);
+	MONT_MAC(t0, t1, t2, u[46], m[12]);
+	MONT_MAC(v0, v1, v2, u[47], m[11]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[10] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 59 */
+	MONT_MUL(s0, s1, s2, a[12], a[47]);
+	MONT_MUL(c0, c1, c2, a[13], a[46]);
+	MONT_MAC(s0, s1, s2, a[14], a[45]);
+	MONT_MAC(c0, c1, c2, a[15], a[44]);
+	MONT_MAC(s0, s1, s2, a[16], a[43]);
+	MONT_MAC(c0, c1, c2, a[17], a[42]);
+	MONT_MAC(s0, s1, s2, a[18], a[41]);
+	MONT_MAC(c0, c1, c2, a[19], a[40]);
+	MONT_MAC(s0, s1, s2, a[20], a[39]);
+	MONT_MAC(c0, c1, c2, a[21], a[38]);
+	MONT_MAC(s0, s1, s2, a[22], a[37]);
+	MONT_MAC(c0, c1, c2, a[23], a[36]);
+	MONT_MAC(s0, s1, s2, a[24], a[35]);
+	MONT_MAC(c0, c1, c2, a[25], a[34]);
+	MONT_MAC(s0, s1, s2, a[26], a[33]);
+	MONT_MAC(c0, c1, c2, a[27], a[32]);
+	MONT_MAC(s0, s1, s2, a[28], a[31]);
+	MONT_MAC(c0, c1, c2, a[29], a[30]);
+	MONT_MAC(t0, t1, t2, u[12], m[47]);
+	MONT_MUL(v0, v1, v2, u[13], m[46]);
+	MONT_MUL(w0, w1, w2, u[14], m[45]);
+	MONT_MAC(t0, t1, t2, u[15], m[44]);
+	MONT_MAC(v0, v1, v2, u[16], m[43]);
+	MONT_MAC(w0, w1, w2, u[17], m[42]);
+	MONT_MAC(t0, t1, t2, u[18], m[41]);
+	MONT_MAC(v0, v1, v2, u[19], m[40]);
+	MONT_MAC(w0, w1, w2, u[20], m[39]);
+	MONT_MAC(t0, t1, t2, u[21], m[38]);
+	MONT_MAC(v0, v1, v2, u[22], m[37]);
+	MONT_MAC(w0, w1, w2, u[23], m[36]);
+	MONT_MAC(t0, t1, t2, u[24], m[35]);
+	MONT_MAC(v0, v1, v2, u[25], m[34]);
+	MONT_MAC(w0, w1, w2, u[26], m[33]);
+	MONT_MAC(t0, t1, t2, u[27], m[32]);
+	MONT_MAC(v0, v1, v2, u[28], m[31]);
+	MONT_MAC(w0, w1, w2, u[29], m[30]);
+	MONT_MAC(t0, t1, t2, u[30], m[29]);
+	MONT_MAC(v0, v1, v2, u[31], m[28]);
+	MONT_MAC(w0, w1, w2, u[32], m[27]);
+	MONT_MAC(t0, t1, t2, u[33], m[26]);
+	MONT_MAC(v0, v1, v2, u[34], m[25]);
+	MONT_MAC(w0, w1, w2, u[35], m[24]);
+	MONT_MAC(t0, t1, t2, u[36], m[23]);
+	MONT_MAC(v0, v1, v2, u[37], m[22]);
+	MONT_MAC(w0, w1, w2, u[38], m[21]);
+	MONT_MAC(t0, t1, t2, u[39], m[20]);
+	MONT_MAC(v0, v1, v2, u[40], m[19]);
+	MONT_MAC(w0, w1, w2, u[41], m[18]);
+	MONT_MAC(t0, t1, t2, u[42], m[17]);
+	MONT_MAC(v0, v1, v2, u[43], m[16]);
+	MONT_MAC(w0, w1, w2, u[44], m[15]);
+	MONT_MAC(t0, t1, t2, u[45], m[14]);
+	MONT_MAC(v0, v1, v2, u[46], m[13]);
+	MONT_MAC(w0, w1, w2, u[47], m[12]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[11] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 60 */
+	MONT_MUL(s0, s1, s2, a[13], a[47]);
+	MONT_MUL(c0, c1, c2, a[14], a[46]);
+	MONT_MAC(s0, s1, s2, a[15], a[45]);
+	MONT_MAC(c0, c1, c2, a[16], a[44]);
+	MONT_MAC(s0, s1, s2, a[17], a[43]);
+	MONT_MAC(c0, c1, c2, a[18], a[42]);
+	MONT_MAC(s0, s1, s2, a[19], a[41]);
+	MONT_MAC(c0, c1, c2, a[20], a[40]);
+	MONT_MAC(s0, s1, s2, a[21], a[39]);
+	MONT_MAC(c0, c1, c2, a[22], a[38]);
+	MONT_MAC(s0, s1, s2, a[23], a[37]);
+	MONT_MAC(c0, c1, c2, a[24], a[36]);
+	MONT_MAC(s0, s1, s2, a[25], a[35]);
+	MONT_MAC(c0, c1, c2, a[26], a[34]);
+	MONT_MAC(s0, s1, s2, a[27], a[33]);
+	MONT_MAC(c0, c1, c2, a[28], a[32]);
+	MONT_MAC(s0, s1, s2, a[29], a[31]);
+	MONT_MAC(t0, t1, t2, a[30], a[30]);
+	MONT_MUL(v0, v1, v2, u[13], m[47]);
+	MONT_MUL(w0, w1, w2, u[14], m[46]);
+	MONT_MAC(t0, t1, t2, u[15], m[45]);
+	MONT_MAC(v0, v1, v2, u[16], m[44]);
+	MONT_MAC(w0, w1, w2, u[17], m[43]);
+	MONT_MAC(t0, t1, t2, u[18], m[42]);
+	MONT_MAC(v0, v1, v2, u[19], m[41]);
+	MONT_MAC(w0, w1, w2, u[20], m[40]);
+	MONT_MAC(t0, t1, t2, u[21], m[39]);
+	MONT_MAC(v0, v1, v2, u[22], m[38]);
+	MONT_MAC(w0, w1, w2, u[23], m[37]);
+	MONT_MAC(t0, t1, t2, u[24], m[36]);
+	MONT_MAC(v0, v1, v2, u[25], m[35]);
+	MONT_MAC(w0, w1, w2, u[26], m[34]);
+	MONT_MAC(t0, t1, t2, u[27], m[33]);
+	MONT_MAC(v0, v1, v2, u[28], m[32]);
+	MONT_MAC(w0, w1, w2, u[29], m[31]);
+	MONT_MAC(t0, t1, t2, u[30], m[30]);
+	MONT_MAC(v0, v1, v2, u[31], m[29]);
+	MONT_MAC(w0, w1, w2, u[32], m[28]);
+	MONT_MAC(t0, t1, t2, u[33], m[27]);
+	MONT_MAC(v0, v1, v2, u[34], m[26]);
+	MONT_MAC(w0, w1, w2, u[35], m[25]);
+	MONT_MAC(t0, t1, t2, u[36], m[24]);
+	MONT_MAC(v0, v1, v2, u[37], m[23]);
+	MONT_MAC(w0, w1, w2, u[38], m[22]);
+	MONT_MAC(t0, t1, t2, u[39], m[21]);
+	MONT_MAC(v0, v1, v2, u[40], m[20]);
+	MONT_MAC(w0, w1, w2, u[41], m[19]);
+	MONT_MAC(t0, t1, t2, u[42], m[18]);
+	MONT_MAC(v0, v1, v2, u[43], m[17]);
+	MONT_MAC(w0, w1, w2, u[44], m[16]);
+	MONT_MAC(t0, t1, t2, u[45], m[15]);
+	MONT_MAC(v0, v1, v2, u[46], m[14]);
+	MONT_MAC(w0, w1, w2, u[47], m[13]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[12] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 61 */
+	MONT_MUL(s0, s1, s2, a[14], a[47]);
+	MONT_MUL(c0, c1, c2, a[15], a[46]);
+	MONT_MAC(s0, s1, s2, a[16], a[45]);
+	MONT_MAC(c0, c1, c2, a[17], a[44]);
+	MONT_MAC(s0, s1, s2, a[18], a[43]);
+	MONT_MAC(c0, c1, c2, a[19], a[42]);
+	MONT_MAC(s0, s1, s2, a[20], a[41]);
+	MONT_MAC(c0, c1, c2, a[21], a[40]);
+	MONT_MAC(s0, s1, s2, a[22], a[39]);
+	MONT_MAC(c0, c1, c2, a[23], a[38]);
+	MONT_MAC(s0, s1, s2, a[24], a[37]);
+	MONT_MAC(c0, c1, c2, a[25], a[36]);
+	MONT_MAC(s0, s1, s2, a[26], a[35]);
+	MONT_MAC(c0, c1, c2, a[27], a[34]);
+	MONT_MAC(s0, s1, s2, a[28], a[33]);
+	MONT_MAC(c0, c1, c2, a[29], a[32]);
+	MONT_MAC(s0, s1, s2, a[30], a[31]);
+	MONT_MAC(t0, t1, t2, u[14], m[47]);
+	MONT_MUL(v0, v1, v2, u[15], m[46]);
+	MONT_MUL(w0, w1, w2, u[16], m[45]);
+	MONT_MAC(t0, t1, t2, u[17], m[44]);
+	MONT_MAC(v0, v1, v2, u[18], m[43]);
+	MONT_MAC(w0, w1, w2, u[19], m[42]);
+	MONT_MAC(t0, t1, t2, u[20], m[41]);
+	MONT_MAC(v0, v1, v2, u[21], m[40]);
+	MONT_MAC(w0, w1, w2, u[22], m[39]);
+	MONT_MAC(t0, t1, t2, u[23], m[38]);
+	MONT_MAC(v0, v1, v2, u[24], m[37]);
+	MONT_MAC(w0, w1, w2, u[25], m[36]);
+	MONT_MAC(t0, t1, t2, u[26], m[35]);
+	MONT_MAC(v0, v1, v2, u[27], m[34]);
+	MONT_MAC(w0, w1, w2, u[28], m[33]);
+	MONT_MAC(t0, t1, t2, u[29], m[32]);
+	MONT_MAC(v0, v1, v2, u[30], m[31]);
+	MONT_MAC(w0, w1, w2, u[31], m[30]);
+	MONT_MAC(t0, t1, t2, u[32], m[29]);
+	MONT_MAC(v0, v1, v2, u[33], m[28]);
+	MONT_MAC(w0, w1, w2, u[34], m[27]);
+	MONT_MAC(t0, t1, t2, u[35], m[26]);
+	MONT_MAC(v0, v1, v2, u[36], m[25]);
+	MONT_MAC(w0, w1, w2, u[37], m[24]);
+	MONT_MAC(t0, t1, t2, u[38], m[23]);
+	MONT_MAC(v0, v1, v2, u[39], m[22]);
+	MONT_MAC(w0, w1, w2, u[40], m[21]);
+	MONT_MAC(t0, t1, t2, u[41], m[20]);
+	MONT_MAC(v0, v1, v2, u[42], m[19]);
+	MONT_MAC(w0, w1, w2, u[43], m[18]);
+	MONT_MAC(t0, t1, t2, u[44], m[17]);
+	MONT_MAC(v0, v1, v2, u[45], m[16]);
+	MONT_MAC(w0, w1, w2, u[46], m[15]);
+	MONT_MAC(t0, t1, t2, u[47], m[14]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[13] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 62 */
+	MONT_MUL(s0, s1, s2, a[15], a[47]);
+	MONT_MUL(c0, c1, c2, a[16], a[46]);
+	MONT_MAC(s0, s1, s2, a[17], a[45]);
+	MONT_MAC(c0, c1, c2, a[18], a[44]);
+	MONT_MAC(s0, s1, s2, a[19], a[43]);
+	MONT_MAC(c0, c1, c2, a[20], a[42]);
+	MONT_MAC(s0, s1, s2, a[21], a[41]);
+	MONT_MAC(c0, c1, c2, a[22], a[40]);
+	MONT_MAC(s0, s1, s2, a[23], a[39]);
+	MONT_MAC(c0, c1, c2, a[24], a[38]);
+	MONT_MAC(s0, s1, s2, a[25], a[37]);
+	MONT_MAC(c0, c1, c2, a[26], a[36]);
+	MONT_MAC(s0, s1, s2, a[27], a[35]);
+	MONT_MAC(c0, c1, c2, a[28], a[34]);
+	MONT_MAC(s0, s1, s2, a[29], a[33]);
+	MONT_MAC(c0, c1, c2, a[30], a[32]);
+	MONT_MAC(t0, t1, t2, a[31], a[31]);
+	MONT_MUL(v0, v1, v2, u[15], m[47]);
+	MONT_MUL(w0, w1, w2, u[16], m[46]);
+	MONT_MAC(t0, t1, t2, u[17], m[45]);
+	MONT_MAC(v0, v1, v2, u[18], m[44]);
+	MONT_MAC(w0, w1, w2, u[19], m[43]);
+	MONT_MAC(t0, t1, t2, u[20], m[42]);
+	MONT_MAC(v0, v1, v2, u[21], m[41]);
+	MONT_MAC(w0, w1, w2, u[22], m[40]);
+	MONT_MAC(t0, t1, t2, u[23], m[39]);
+	MONT_MAC(v0, v1, v2, u[24], m[38]);
+	MONT_MAC(w0, w1, w2, u[25], m[37]);
+	MONT_MAC(t0, t1, t2, u[26], m[36]);
+	MONT_MAC(v0, v1, v2, u[27], m[35]);
+	MONT_MAC(w0, w1, w2, u[28], m[34]);
+	MONT_MAC(t0, t1, t2, u[29], m[33]);
+	MONT_MAC(v0, v1, v2, u[30], m[32]);
+	MONT_MAC(w0, w1, w2, u[31], m[31]);
+	MONT_MAC(t0, t1, t2, u[32], m[30]);
+	MONT_MAC(v0, v1, v2, u[33], m[29]);
+	MONT_MAC(w0, w1, w2, u[34], m[28]);
+	MONT_MAC(t0, t1, t2, u[35], m[27]);
+	MONT_MAC(v0, v1, v2, u[36], m[26]);
+	MONT_MAC(w0, w1, w2, u[37], m[25]);
+	MONT_MAC(t0, t1, t2, u[38], m[24]);
+	MONT_MAC(v0, v1, v2, u[39], m[23]);
+	MONT_MAC(w0, w1, w2, u[40], m[22]);
+	MONT_MAC(t0, t1, t2, u[41], m[21]);
+	MONT_MAC(v0, v1, v2, u[42], m[20]);
+	MONT_MAC(w0, w1, w2, u[43], m[19]);
+	MONT_MAC(t0, t1, t2, u[44], m[18]);
+	MONT_MAC(v0, v1, v2, u[45], m[17]);
+	MONT_MAC(w0, w1, w2, u[46], m[16]);
+	MONT_MAC(t0, t1, t2, u[47], m[15]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[14] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 63 */
+	MONT_MUL(s0, s1, s2, a[16], a[47]);
+	MONT_MUL(c0, c1, c2, a[17], a[46]);
+	MONT_MAC(s0, s1, s2, a[18], a[45]);
+	MONT_MAC(c0, c1, c2, a[19], a[44]);
+	MONT_MAC(s0, s1, s2, a[20], a[43]);
+	MONT_MAC(c0, c1, c2, a[21], a[42]);
+	MONT_MAC(s0, s1, s2, a[22], a[41]);
+	MONT_MAC(c0, c1, c2, a[23], a[40]);
+	MONT_MAC(s0, s1, s2, a[24], a[39]);
+	MONT_MAC(c0, c1, c2, a[25], a[38]);
+	MONT_MAC(s0, s1, s2, a[26], a[37]);
+	MONT_MAC(c0, c1, c2, a[27], a[36]);
+	MONT_MAC(s0, s1, s2, a[28], a[35]);
+	MONT_MAC(c0, c1, c2, a[29], a[34]);
+	MONT_MAC(s0, s1, s2, a[30], a[33]);
+	MONT_MAC(c0, c1, c2, a[31], a[32]);
+	MONT_MAC(t0, t1, t2, u[16], m[47]);
+	MONT_MUL(v0, v1, v2, u[17], m[46]);
+	MONT_MUL(w0, w1, w2, u[18], m[45]);
+	MONT_MAC(t0, t1, t2, u[19], m[44]);
+	MONT_MAC(v0, v1, v2, u[20], m[43]);
+	MONT_MAC(w0, w1, w2, u[21], m[42]);
+	MONT_MAC(t0, t1, t2, u[22], m[41]);
+	MONT_MAC(v0, v1, v2, u[23], m[40]);
+	MONT_MAC(w0, w1, w2, u[24], m[39]);
+	MONT_MAC(t0, t1, t2, u[25], m[38]);
+	MONT_MAC(v0, v1, v2, u[26], m[37]);
+	MONT_MAC(w0, w1, w2, u[27], m[36]);
+	MONT_MAC(t0, t1, t2, u[28], m[35]);
+	MONT_MAC(v0, v1, v2, u[29], m[34]);
+	MONT_MAC(w0, w1, w2, u[30], m[33]);
+	MONT_MAC(t0, t1, t2, u[31], m[32]);
+	MONT_MAC(v0, v1, v2, u[32], m[31]);
+	MONT_MAC(w0, w1, w2, u[33], m[30]);
+	MONT_MAC(t0, t1, t2, u[34], m[29]);
+	MONT_MAC(v0, v1, v2, u[35], m[28]);
+	MONT_MAC(w0, w1, w2, u[36], m[27]);
+	MONT_MAC(t0, t1, t2, u[37], m[26]);
+	MONT_MAC(v0, v1, v2, u[38], m[25]);
+	MONT_MAC(w0, w1, w2, u[39], m[24]);
+	MONT_MAC(t0, t1, t2, u[40], m[23]);
+	MONT_MAC(v0, v1, v2, u[41], m[22]);
+	MONT_MAC(w0, w1, w2, u[42], m[21]);
+	MONT_MAC(t0, t1, t2, u[43], m[20]);
+	MONT_MAC(v0, v1, v2, u[44], m[19]);
+	MONT_MAC(w0, w1, w2, u[45], m[18]);
+	MONT_MAC(t0, t1, t2, u[46], m[17]);
+	MONT_MAC(v0, v1, v2, u[47], m[16]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[15] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 64 */
+	MONT_MUL(s0, s1, s2, a[17], a[47]);
+	MONT_MUL(c0, c1, c2, a[18], a[46]);
+	MONT_MAC(s0, s1, s2, a[19], a[45]);
+	MONT_MAC(c0, c1, c2, a[20], a[44]);
+	MONT_MAC(s0, s1, s2, a[21], a[43]);
+	MONT_MAC(c0, c1, c2, a[22], a[42]);
+	MONT_MAC(s0, s1, s2, a[23], a[41]);
+	MONT_MAC(c0, c1, c2, a[24], a[40]);
+	MONT_MAC(s0, s1, s2, a[25], a[39]);
+	MONT_MAC(c0, c1, c2, a[26], a[38]);
+	MONT_MAC(s0, s1, s2, a[27], a[37]);
+	MONT_MAC(c0, c1, c2, a[28], a[36]);
+	MONT_MAC(s0, s1, s2, a[29], a[35]);
+	MONT_MAC(c0, c1, c2, a[30], a[34]);
+	MONT_MAC(s0, s1, s2, a[31], a[33]);
+	MONT_MAC(t0, t1, t2, a[32], a[32]);
+	MONT_MUL(v0, v1, v2, u[17], m[47]);
+	MONT_MUL(w0, w1, w2, u[18], m[46]);
+	MONT_MAC(t0, t1, t2, u[19], m[45]);
+	MONT_MAC(v0, v1, v2, u[20], m[44]);
+	MONT_MAC(w0, w1, w2, u[21], m[43]);
+	MONT_MAC(t0, t1, t2, u[22], m[42]);
+	MONT_MAC(v0, v1, v2, u[23], m[41]);
+	MONT_MAC(w0, w1, w2, u[24], m[40]);
+	MONT_MAC(t0, t1, t2, u[25], m[39]);
+	MONT_MAC(v0, v1, v2, u[26], m[38]);
+	MONT_MAC(w0, w1, w2, u[27], m[37]);
+	MONT_MAC(t0, t1, t2, u[28], m[36]);
+	MONT_MAC(v0, v1, v2, u[29], m[35]);
+	MONT_MAC(w0, w1, w2, u[30], m[34]);
+	MONT_MAC(t0, t1, t2, u[31], m[33]);
+	MONT_MAC(v0, v1, v2, u[32], m[32]);
+	MONT_MAC(w0, w1, w2, u[33], m[31]);
+	MONT_MAC(t0, t1, t2, u[34], m[30]);
+	MONT_MAC(v0, v1, v2, u[35], m[29]);
+	MONT_MAC(w0, w1, w2, u[36], m[28]);
+	MONT_MAC(t0, t1, t2, u[37], m[27]);
+	MONT_MAC(v0, v1, v2, u[38], m[26]);
+	MONT_MAC(w0, w1, w2, u[39], m[25]);
+	MONT_MAC(t0, t1, t2, u[40], m[24]);
+	MONT_MAC(v0, v1, v2, u[41], m[23]);
+	MONT_MAC(w0, w1, w2, u[42], m[22]);
+	MONT_MAC(t0, t1, t2, u[43], m[21]);
+	MONT_MAC(v0, v1, v2, u[44], m[20]);
+	MONT_MAC(w0, w1, w2, u[45], m[19]);
+	MONT_MAC(t0, t1, t2, u[46], m[18]);
+	MONT_MAC(v0, v1, v2, u[47], m[17]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[16] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 65 */
+	MONT_MUL(s0, s1, s2, a[18], a[47]);
+	MONT_MUL(c0, c1, c2, a[19], a[46]);
+	MONT_MAC(s0, s1, s2, a[20], a[45]);
+	MONT_MAC(c0, c1, c2, a[21], a[44]);
+	MONT_MAC(s0, s1, s2, a[22], a[43]);
+	MONT_MAC(c0, c1, c2, a[23], a[42]);
+	MONT_MAC(s0, s1, s2, a[24], a[41]);
+	MONT_MAC(c0, c1, c2, a[25], a[40]);
+	MONT_MAC(s0, s1, s2, a[26], a[39]);
+	MONT_MAC(c0, c1, c2, a[27], a[38]);
+	MONT_MAC(s0, s1, s2, a[28], a[37]);
+	MONT_MAC(c0, c1, c2, a[29], a[36]);
+	MONT_MAC(s0, s1, s2, a[30], a[35]);
+	MONT_MAC(c0, c1, c2, a[31], a[34]);
+	MONT_MAC(s0, s1, s2, a[32], a[33]);
+	MONT_MAC(t0, t1, t2, u[18], m[47]);
+	MONT_MUL(v0, v1, v2, u[19], m[46]);
+	MONT_MUL(w0, w1, w2, u[20], m[45]);
+	MONT_MAC(t0, t1, t2, u[21], m[44]);
+	MONT_MAC(v0, v1, v2, u[22], m[43]);
+	MONT_MAC(w0, w1, w2, u[23], m[42]);
+	MONT_MAC(t0, t1, t2, u[24], m[41]);
+	MONT_MAC(v0, v1, v2, u[25], m[40]);
+	MONT_MAC(w0, w1, w2, u[26], m[39]);
+	MONT_MAC(t0, t1, t2, u[27], m[38]);
+	MONT_MAC(v0, v1, v2, u[28], m[37]);
+	MONT_MAC(w0, w1, w2, u[29], m[36]);
+	MONT_MAC(t0, t1, t2, u[30], m[35]);
+	MONT_MAC(v0, v1, v2, u[31], m[34]);
+	MONT_MAC(w0, w1, w2, u[32], m[33]);
+	MONT_MAC(t0, t1, t2, u[33], m[32]);
+	MONT_MAC(v0, v1, v2, u[34], m[31]);
+	MONT_MAC(w0, w1, w2, u[35], m[30]);
+	MONT_MAC(t0, t1, t2, u[36], m[29]);
+	MONT_MAC(v0, v1, v2, u[37], m[28]);
+	MONT_MAC(w0, w1, w2, u[38], m[27]);
+	MONT_MAC(t0, t1, t2, u[39], m[26]);
+	MONT_MAC(v0, v1, v2, u[40], m[25]);
+	MONT_MAC(w0, w1, w2, u[41], m[24]);
+	MONT_MAC(t0, t1, t2, u[42], m[23]);
+	MONT_MAC(v0, v1, v2, u[43], m[22]);
+	MONT_MAC(w0, w1, w2, u[44], m[21]);
+	MONT_MAC(t0, t1, t2, u[45], m[20]);
+	MONT_MAC(v0, v1, v2, u[46], m[19]);
+	MONT_MAC(w0, w1, w2, u[47], m[18]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[17] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 66 */
+	MONT_MUL(s0, s1, s2, a[19], a[47]);
+	MONT_MUL(c0, c1, c2, a[20], a[46]);
+	MONT_MAC(s0, s1, s2, a[21], a[45]);
+	MONT_MAC(c0, c1, c2, a[22], a[44]);
+	MONT_MAC(s0, s1, s2, a[23], a[43]);
+	MONT_MAC(c0, c1, c2, a[24], a[42]);
+	MONT_MAC(s0, s1, s2, a[25], a[41]);
+	MONT_MAC(c0, c1, c2, a[26], a[40]);
+	MONT_MAC(s0, s1, s2, a[27], a[39]);
+	MONT_MAC(c0, c1, c2, a[28], a[38]);
+	MONT_MAC(s0, s1, s2, a[29], a[37]);
+	MONT_MAC(c0, c1, c2, a[30], a[36]);
+	MONT_MAC(s0, s1, s2, a[31], a[35]);
+	MONT_MAC(c0, c1, c2, a[32], a[34]);
+	MONT_MAC(t0, t1, t2, a[33], a[33]);
+	MONT_MUL(v0, v1, v2, u[19], m[47]);
+	MONT_MUL(w0, w1, w2, u[20], m[46]);
+	MONT_MAC(t0, t1, t2, u[21], m[45]);
+	MONT_MAC(v0, v1, v2, u[22], m[44]);
+	MONT_MAC(w0, w1, w2, u[23], m[43]);
+	MONT_MAC(t0, t1, t2, u[24], m[42]);
+	MONT_MAC(v0, v1, v2, u[25], m[41]);
+	MONT_MAC(w0, w1, w2, u[26], m[40]);
+	MONT_MAC(t0, t1, t2, u[27], m[39]);
+	MONT_MAC(v0, v1, v2, u[28], m[38]);
+	MONT_MAC(w0, w1, w2, u[29], m[37]);
+	MONT_MAC(t0, t1, t2, u[30], m[36]);
+	MONT_MAC(v0, v1, v2, u[31], m[35]);
+	MONT_MAC(w0, w1, w2, u[32], m[34]);
+	MONT_MAC(t0, t1, t2, u[33], m[33]);
+	MONT_MAC(v0, v1, v2, u[34], m[32]);
+	MONT_MAC(w0, w1, w2, u[35], m[31]);
+	MONT_MAC(t0, t1, t2, u[36], m[30]);
+	MONT_MAC(v0, v1, v2, u[37], m[29]);
+	MONT_MAC(w0, w1, w2, u[38], m[28]);
+	MONT_MAC(t0, t1, t2, u[39], m[27]);
+	MONT_MAC(v0, v1, v2, u[40], m[26]);
+	MONT_MAC(w0, w1, w2, u[41], m[25]);
+	MONT_MAC(t0, t1, t2, u[42], m[24]);
+	MONT_MAC(v0, v1, v2, u[43], m[23]);
+	MONT_MAC(w0, w1, w2, u[44], m[22]);
+	MONT_MAC(t0, t1, t2, u[45], m[21]);
+	MONT_MAC(v0, v1, v2, u[46], m[20]);
+	MONT_MAC(w0, w1, w2, u[47], m[19]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[18] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 67 */
+	MONT_MUL(s0, s1, s2, a[20], a[47]);
+	MONT_MUL(c0, c1, c2, a[21], a[46]);
+	MONT_MAC(s0, s1, s2, a[22], a[45]);
+	MONT_MAC(c0, c1, c2, a[23], a[44]);
+	MONT_MAC(s0, s1, s2, a[24], a[43]);
+	MONT_MAC(c0, c1, c2, a[25], a[42]);
+	MONT_MAC(s0, s1, s2, a[26], a[41]);
+	MONT_MAC(c0, c1, c2, a[27], a[40]);
+	MONT_MAC(s0, s1, s2, a[28], a[39]);
+	MONT_MAC(c0, c1, c2, a[29], a[38]);
+	MONT_MAC(s0, s1, s2, a[30], a[37]);
+	MONT_MAC(c0, c1, c2, a[31], a[36]);
+	MONT_MAC(s0, s1, s2, a[32], a[35]);
+	MONT_MAC(c0, c1, c2, a[33], a[34]);
+	MONT_MAC(t0, t1, t2, u[20], m[47]);
+	MONT_MUL(v0, v1, v2, u[21], m[46]);
+	MONT_MUL(w0, w1, w2, u[22], m[45]);
+	MONT_MAC(t0, t1, t2, u[23], m[44]);
+	MONT_MAC(v0, v1, v2, u[24], m[43]);
+	MONT_MAC(w0, w1, w2, u[25], m[42]);
+	MONT_MAC(t0, t1, t2, u[26], m[41]);
+	MONT_MAC(v0, v1, v2, u[27], m[40]);
+	MONT_MAC(w0, w1, w2, u[28], m[39]);
+	MONT_MAC(t0, t1, t2, u[29], m[38]);
+	MONT_MAC(v0, v1, v2, u[30], m[37]);
+	MONT_MAC(w0, w1, w2, u[31], m[36]);
+	MONT_MAC(t0, t1, t2, u[32], m[35]);
+	MONT_MAC(v0, v1, v2, u[33], m[34]);
+	MONT_MAC(w0, w1, w2, u[34], m[33]);
+	MONT_MAC(t0, t1, t2, u[35], m[32]);
+	MONT_MAC(v0, v1, v2, u[36], m[31]);
+	MONT_MAC(w0, w1, w2, u[37], m[30]);
+	MONT_MAC(t0, t1, t2, u[38], m[29]);
+	MONT_MAC(v0, v1, v2, u[39], m[28]);
+	MONT_MAC(w0, w1, w2, u[40], m[27]);
+	MONT_MAC(t0, t1, t2, u[41], m[26]);
+	MONT_MAC(v0, v1, v2, u[42], m[25]);
+	MONT_MAC(w0, w1, w2, u[43], m[24]);
+	MONT_MAC(t0, t1, t2, u[44], m[23]);
+	MONT_MAC(v0, v1, v2, u[45], m[22]);
+	MONT_MAC(w0, w1, w2, u[46], m[21]);
+	MONT_MAC(t0, t1, t2, u[47], m[20]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[19] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 68 */
+	MONT_MUL(s0, s1, s2, a[21], a[47]);
+	MONT_MUL(c0, c1, c2, a[22], a[46]);
+	MONT_MAC(s0, s1, s2, a[23], a[45]);
+	MONT_MAC(c0, c1, c2, a[24], a[44]);
+	MONT_MAC(s0, s1, s2, a[25], a[43]);
+	MONT_MAC(c0, c1, c2, a[26], a[42]);
+	MONT_MAC(s0, s1, s2, a[27], a[41]);
+	MONT_MAC(c0, c1, c2, a[28], a[40]);
+	MONT_MAC(s0, s1, s2, a[29], a[39]);
+	MONT_MAC(c0, c1, c2, a[30], a[38]);
+	MONT_MAC(s0, s1, s2, a[31], a[37]);
+	MONT_MAC(c0, c1, c2, a[32], a[36]);
+	MONT_MAC(s0, s1, s2, a[33], a[35]);
+	MONT_MAC(t0, t1, t2, a[34], a[34]);
+	MONT_MUL(v0, v1, v2, u[21], m[47]);
+	MONT_MUL(w0, w1, w2, u[22], m[46]);
+	MONT_MAC(t0, t1, t2, u[23], m[45]);
+	MONT_MAC(v0, v1, v2, u[24], m[44]);
+	MONT_MAC(w0, w1, w2, u[25], m[43]);
+	MONT_MAC(t0, t1, t2, u[26], m[42]);
+	MONT_MAC(v0, v1, v2, u[27], m[41]);
+	MONT_MAC(w0, w1, w2, u[28], m[40]);
+	MONT_MAC(t0, t1, t2, u[29], m[39]);
+	MONT_MAC(v0, v1, v2, u[30], m[38]);
+	MONT_MAC(w0, w1, w2, u[31], m[37]);
+	MONT_MAC(t0, t1, t2, u[32], m[36]);
+	MONT_MAC(v0, v1, v2, u[33], m[35]);
+	MONT_MAC(w0, w1, w2, u[34], m[34]);
+	MONT_MAC(t0, t1, t2, u[35], m[33]);
+	MONT_MAC(v0, v1, v2, u[36], m[32]);
+	MONT_MAC(w0, w1, w2, u[37], m[31]);
+	MONT_MAC(t0, t1, t2, u[38], m[30]);
+	MONT_MAC(v0, v1, v2, u[39], m[29]);
+	MONT_MAC(w0, w1, w2, u[40], m[28]);
+	MONT_MAC(t0, t1, t2, u[41], m[27]);
+	MONT_MAC(v0, v1, v2, u[42], m[26]);
+	MONT_MAC(w0, w1, w2, u[43], m[25]);
+	MONT_MAC(t0, t1, t2, u[44], m[24]);
+	MONT_MAC(v0, v1, v2, u[45], m[23]);
+	MONT_MAC(w0, w1, w2, u[46], m[22]);
+	MONT_MAC(t0, t1, t2, u[47], m[21]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[20] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 69 */
+	MONT_MUL(s0, s1, s2, a[22], a[47]);
+	MONT_MUL(c0, c1, c2, a[23], a[46]);
+	MONT_MAC(s0, s1, s2, a[24], a[45]);
+	MONT_MAC(c0, c1, c2, a[25], a[44]);
+	MONT_MAC(s0, s1, s2, a[26], a[43]);
+	MONT_MAC(c0, c1, c2, a[27], a[42]);
+	MONT_MAC(s0, s1, s2, a[28], a[41]);
+	MONT_MAC(c0, c1, c2, a[29], a[40]);
+	MONT_MAC(s0, s1, s2, a[30], a[39]);
+	MONT_MAC(c0, c1, c2, a[31], a[38]);
+	MONT_MAC(s0, s1, s2, a[32], a[37]);
+	MONT_MAC(c0, c1, c2, a[33], a[36]);
+	MONT_MAC(s0, s1, s2, a[34], a[35]);
+	MONT_MAC(t0, t1, t2, u[22], m[47]);
+	MONT_MUL(v0, v1, v2, u[23], m[46]);
+	MONT_MUL(w0, w1, w2, u[24], m[45]);
+	MONT_MAC(t0, t1, t2, u[25], m[44]);
+	MONT_MAC(v0, v1, v2, u[26], m[43]);
+	MONT_MAC(w0, w1, w2, u[27], m[42]);
+	MONT_MAC(t0, t1, t2, u[28], m[41]);
+	MONT_MAC(v0, v1, v2, u[29], m[40]);
+	MONT_MAC(w0, w1, w2, u[30], m[39]);
+	MONT_MAC(t0, t1, t2, u[31], m[38]);
+	MONT_MAC(v0, v1, v2, u[32], m[37]);
+	MONT_MAC(w0, w1, w2, u[33], m[36]);
+	MONT_MAC(t0, t1, t2, u[34], m[35]);
+	MONT_MAC(v0, v1, v2, u[35], m[34]);
+	MONT_MAC(w0, w1, w2, u[36], m[33]);
+	MONT_MAC(t0, t1, t2, u[37], m[32]);
+	MONT_MAC(v0, v1, v2, u[38], m[31]);
+	MONT_MAC(w0, w1, w2, u[39], m[30]);
+	MONT_MAC(t0, t1, t2, u[40], m[29]);
+	MONT_MAC(v0, v1, v2, u[41], m[28]);
+	MONT_MAC(w0, w1, w2, u[42], m[27]);
+	MONT_MAC(t0, t1, t2, u[43], m[26]);
+	MONT_MAC(v0, v1, v2, u[44], m[25]);
+	MONT_MAC(w0, w1, w2, u[45], m[24]);
+	MONT_MAC(t0, t1, t2, u[46], m[23]);
+	MONT_MAC(v0, v1, v2, u[47], m[22]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[21] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 70 */
+	MONT_MUL(s0, s1, s2, a[23], a[47]);
+	MONT_MUL(c0, c1, c2, a[24], a[46]);
+	MONT_MAC(s0, s1, s2, a[25], a[45]);
+	MONT_MAC(c0, c1, c2, a[26], a[44]);
+	MONT_MAC(s0, s1, s2, a[27], a[43]);
+	MONT_MAC(c0, c1, c2, a[28], a[42]);
+	MONT_MAC(s0, s1, s2, a[29], a[41]);
+	MONT_MAC(c0, c1, c2, a[30], a[40]);
+	MONT_MAC(s0, s1, s2, a[31], a[39]);
+	MONT_MAC(c0, c1, c2, a[32], a[38]);
+	MONT_MAC(s0, s1, s2, a[33], a[37]);
+	MONT_MAC(c0, c1, c2, a[34], a[36]);
+	MONT_MAC(t0, t1, t2, a[35], a[35]);
+	MONT_MUL(v0, v1, v2, u[23], m[47]);
+	MONT_MUL(w0, w1, w2, u[24], m[46]);
+	MONT_MAC(t0, t1, t2, u[25], m[45]);
+	MONT_MAC(v0, v1, v2, u[26], m[44]);
+	MONT_MAC(w0, w1, w2, u[27], m[43]);
+	MONT_MAC(t0, t1, t2, u[28], m[42]);
+	MONT_MAC(v0, v1, v2, u[29], m[41]);
+	MONT_MAC(w0, w1, w2, u[30], m[40]);
+	MONT_MAC(t0, t1, t2, u[31], m[39]);
+	MONT_MAC(v0, v1, v2, u[32], m[38]);
+	MONT_MAC(w0, w1, w2, u[33], m[37]);
+	MONT_MAC(t0, t1, t2, u[34], m[36]);
+	MONT_MAC(v0, v1, v2, u[35], m[35]);
+	MONT_MAC(w0, w1, w2, u[36], m[34]);
+	MONT_MAC(t0, t1, t2, u[37], m[33]);
+	MONT_MAC(v0, v1, v2, u[38], m[32]);
+	MONT_MAC(w0, w1, w2, u[39], m[31]);
+	MONT_MAC(t0, t1, t2, u[40], m[30]);
+	MONT_MAC(v0, v1, v2, u[41], m[29]);
+	MONT_MAC(w0, w1, w2, u[42], m[28]);
+	MONT_MAC(t0, t1, t2, u[43], m[27]);
+	MONT_MAC(v0, v1, v2, u[44], m[26]);
+	MONT_MAC(w0, w1, w2, u[45], m[25]);
+	MONT_MAC(t0, t1, t2, u[46], m[24]);
+	MONT_MAC(v0, v1, v2, u[47], m[23]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[22] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 71 */
+	MONT_MUL(s0, s1, s2, a[24], a[47]);
+	MONT_MUL(c0, c1, c2, a[25], a[46]);
+	MONT_MAC(s0, s1, s2, a[26], a[45]);
+	MONT_MAC(c0, c1, c2, a[27], a[44]);
+	MONT_MAC(s0, s1, s2, a[28], a[43]);
+	MONT_MAC(c0, c1, c2, a[29], a[42]);
+	MONT_MAC(s0, s1, s2, a[30], a[41]);
+	MONT_MAC(c0, c1, c2, a[31], a[40]);
+	MONT_MAC(s0, s1, s2, a[32], a[39]);
+	MONT_MAC(c0, c1, c2, a[33], a[38]);
+	MONT_MAC(s0, s1, s2, a[34], a[37]);
+	MONT_MAC(c0, c1, c2, a[35], a[36]);
+	MONT_MAC(t0, t1, t2, u[24], m[47]);
+	MONT_MUL(v0, v1, v2, u[25], m[46]);
+	MONT_MUL(w0, w1, w2, u[26], m[45]);
+	MONT_MAC(t0, t1, t2, u[27], m[44]);
+	MONT_MAC(v0, v1, v2, u[28], m[43]);
+	MONT_MAC(w0, w1, w2, u[29], m[42]);
+	MONT_MAC(t0, t1, t2, u[30], m[41]);
+	MONT_MAC(v0, v1, v2, u[31], m[40]);
+	MONT_MAC(w0, w1, w2, u[32], m[39]);
+	MONT_MAC(t0, t1, t2, u[33], m[38]);
+	MONT_MAC(v0, v1, v2, u[34], m[37]);
+	MONT_MAC(w0, w1, w2, u[35], m[36]);
+	MONT_MAC(t0, t1, t2, u[36], m[35]);
+	MONT_MAC(v0, v1, v2, u[37], m[34]);
+	MONT_MAC(w0, w1, w2, u[38], m[33]);
+	MONT_MAC(t0, t1, t2, u[39], m[32]);
+	MONT_MAC(v0, v1, v2, u[40], m[31]);
+	MONT_MAC(w0, w1, w2, u[41], m[30]);
+	MONT_MAC(t0, t1, t2, u[42], m[29]);
+	MONT_MAC(v0, v1, v2, u[43], m[28]);
+	MONT_MAC(w0, w1, w2, u[44], m[27]);
+	MONT_MAC(t0, t1, t2, u[45], m[26]);
+	MONT_MAC(v0, v1, v2, u[46], m[25]);
+	MONT_MAC(w0, w1, w2, u[47], m[24]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[23] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 72 */
+	MONT_MUL(s0, s1, s2, a[25], a[47]);
+	MONT_MUL(c0, c1, c2, a[26], a[46]);
+	MONT_MAC(s0, s1, s2, a[27], a[45]);
+	MONT_MAC(c0, c1, c2, a[28], a[44]);
+	MONT_MAC(s0, s1, s2, a[29], a[43]);
+	MONT_MAC(c0, c1, c2, a[30], a[42]);
+	MONT_MAC(s0, s1, s2, a[31], a[41]);
+	MONT_MAC(c0, c1, c2, a[32], a[40]);
+	MONT_MAC(s0, s1, s2, a[33], a[39]);
+	MONT_MAC(c0, c1, c2, a[34], a[38]);
+	MONT_MAC(s0, s1, s2, a[35], a[37]);
+	MONT_MAC(t0, t1, t2, a[36], a[36]);
+	MONT_MUL(v0, v1, v2, u[25], m[47]);
+	MONT_MUL(w0, w1, w2, u[26], m[46]);
+	MONT_MAC(t0, t1, t2, u[27], m[45]);
+	MONT_MAC(v0, v1, v2, u[28], m[44]);
+	MONT_MAC(w0, w1, w2, u[29], m[43]);
+	MONT_MAC(t0, t1, t2, u[30], m[42]);
+	MONT_MAC(v0, v1, v2, u[31], m[41]);
+	MONT_MAC(w0, w1, w2, u[32], m[40]);
+	MONT_MAC(t0, t1, t2, u[33], m[39]);
+	MONT_MAC(v0, v1, v2, u[34], m[38]);
+	MONT_MAC(w0, w1, w2, u[35], m[37]);
+	MONT_MAC(t0, t1, t2, u[36], m[36]);
+	MONT_MAC(v0, v1, v2, u[37], m[35]);
+	MONT_MAC(w0, w1, w2, u[38], m[34]);
+	MONT_MAC(t0, t1, t2, u[39], m[33]);
+	MONT_MAC(v0, v1, v2, u[40], m[32]);
+	MONT_MAC(w0, w1, w2, u[41], m[31]);
+	MONT_MAC(t0, t1, t2, u[42], m[30]);
+	MONT_MAC(v0, v1, v2, u[43], m[29]);
+	MONT_MAC(w0, w1, w2, u[44], m[28]);
+	MONT_MAC(t0, t1, t2, u[45], m[27]);
+	MONT_MAC(v0, v1, v2, u[46], m[26]);
+	MONT_MAC(w0, w1, w2, u[47], m[25]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[24] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 73 */
+	MONT_MUL(s0, s1, s2, a[26], a[47]);
+	MONT_MUL(c0, c1, c2, a[27], a[46]);
+	MONT_MAC(s0, s1, s2, a[28], a[45]);
+	MONT_MAC(c0, c1, c2, a[29], a[44]);
+	MONT_MAC(s0, s1, s2, a[30], a[43]);
+	MONT_MAC(c0, c1, c2, a[31], a[42]);
+	MONT_MAC(s0, s1, s2, a[32], a[41]);
+	MONT_MAC(c0, c1, c2, a[33], a[40]);
+	MONT_MAC(s0, s1, s2, a[34], a[39]);
+	MONT_MAC(c0, c1, c2, a[35], a[38]);
+	MONT_MAC(s0, s1, s2, a[36], a[37]);
+	MONT_MAC(t0, t1, t2, u[26], m[47]);
+	MONT_MUL(v0, v1, v2, u[27], m[46]);
+	MONT_MUL(w0, w1, w2, u[28], m[45]);
+	MONT_MAC(t0, t1, t2, u[29], m[44]);
+	MONT_MAC(v0, v1, v2, u[30], m[43]);
+	MONT_MAC(w0, w1, w2, u[31], m[42]);
+	MONT_MAC(t0, t1, t2, u[32], m[41]);
+	MONT_MAC(v0, v1, v2, u[33], m[40]);
+	MONT_MAC(w0, w1, w2, u[34], m[39]);
+	MONT_MAC(t0, t1, t2, u[35], m[38]);
+	MONT_MAC(v0, v1, v2, u[36], m[37]);
+	MONT_MAC(w0, w1, w2, u[37], m[36]);
+	MONT_MAC(t0, t1, t2, u[38], m[35]);
+	MONT_MAC(v0, v1, v2, u[39], m[34]);
+	MONT_MAC(w0, w1, w2, u[40], m[33]);
+	MONT_MAC(t0, t1, t2, u[41], m[32]);
+	MONT_MAC(v0, v1, v2, u[42], m[31]);
+	MONT_MAC(w0, w1, w2, u[43], m[30]);
+	MONT_MAC(t0, t1, t2, u[44], m[29]);
+	MONT_MAC(v0, v1, v2, u[45], m[28]);
+	MONT_MAC(w0, w1, w2, u[46], m[27]);
+	MONT_MAC(t0, t1, t2, u[47], m[26]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[25] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 74 */
+	MONT_MUL(s0, s1, s2, a[27], a[47]);
+	MONT_MUL(c0, c1, c2, a[28], a[46]);
+	MONT_MAC(s0, s1, s2, a[29], a[45]);
+	MONT_MAC(c0, c1, c2, a[30], a[44]);
+	MONT_MAC(s0, s1, s2, a[31], a[43]);
+	MONT_MAC(c0, c1, c2, a[32], a[42]);
+	MONT_MAC(s0, s1, s2, a[33], a[41]);
+	MONT_MAC(c0, c1, c2, a[34], a[40]);
+	MONT_MAC(s0, s1, s2, a[35], a[39]);
+	MONT_MAC(c0, c1, c2, a[36], a[38]);
+	MONT_MAC(t0, t1, t2, a[37], a[37]);
+	MONT_MUL(v0, v1, v2, u[27], m[47]);
+	MONT_MUL(w0, w1, w2, u[28], m[46]);
+	MONT_MAC(t0, t1, t2, u[29], m[45]);
+	MONT_MAC(v0, v1, v2, u[30], m[44]);
+	MONT_MAC(w0, w1, w2, u[31], m[43]);
+	MONT_MAC(t0, t1, t2, u[32], m[42]);
+	MONT_MAC(v0, v1, v2, u[33], m[41]);
+	MONT_MAC(w0, w1, w2, u[34], m[40]);
+	MONT_MAC(t0, t1, t2, u[35], m[39]);
+	MONT_MAC(v0, v1, v2, u[36], m[38]);
+	MONT_MAC(w0, w1, w2, u[37], m[37]);
+	MONT_MAC(t0, t1, t2, u[38], m[36]);
+	MONT_MAC(v0, v1, v2, u[39], m[35]);
+	MONT_MAC(w0, w1, w2, u[40], m[34]);
+	MONT_MAC(t0, t1, t2, u[41], m[33]);
+	MONT_MAC(v0, v1, v2, u[42], m[32]);
+	MONT_MAC(w0, w1, w2, u[43], m[31]);
+	MONT_MAC(t0, t1, t2, u[44], m[30]);
+	MONT_MAC(v0, v1, v2, u[45], m[29]);
+	MONT_MAC(w0, w1, w2, u[46], m[28]);
+	MONT_MAC(t0, t1, t2, u[47], m[27]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[26] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 75 */
+	MONT_MUL(s0, s1, s2, a[28], a[47]);
+	MONT_MUL(c0, c1, c2, a[29], a[46]);
+	MONT_MAC(s0, s1, s2, a[30], a[45]);
+	MONT_MAC(c0, c1, c2, a[31], a[44]);
+	MONT_MAC(s0, s1, s2, a[32], a[43]);
+	MONT_MAC(c0, c1, c2, a[33], a[42]);
+	MONT_MAC(s0, s1, s2, a[34], a[41]);
+	MONT_MAC(c0, c1, c2, a[35], a[40]);
+	MONT_MAC(s0, s1, s2, a[36], a[39]);
+	MONT_MAC(c0, c1, c2, a[37], a[38]);
+	MONT_MAC(t0, t1, t2, u[28], m[47]);
+	MONT_MUL(v0, v1, v2, u[29], m[46]);
+	MONT_MUL(w0, w1, w2, u[30], m[45]);
+	MONT_MAC(t0, t1, t2, u[31], m[44]);
+	MONT_MAC(v0, v1, v2, u[32], m[43]);
+	MONT_MAC(w0, w1, w2, u[33], m[42]);
+	MONT_MAC(t0, t1, t2, u[34], m[41]);
+	MONT_MAC(v0, v1, v2, u[35], m[40]);
+	MONT_MAC(w0, w1, w2, u[36], m[39]);
+	MONT_MAC(t0, t1, t2, u[37], m[38]);
+	MONT_MAC(v0, v1, v2, u[38], m[37]);
+	MONT_MAC(w0, w1, w2, u[39], m[36]);
+	MONT_MAC(t0, t1, t2, u[40], m[35]);
+	MONT_MAC(v0, v1, v2, u[41], m[34]);
+	MONT_MAC(w0, w1, w2, u[42], m[33]);
+	MONT_MAC(t0, t1, t2, u[43], m[32]);
+	MONT_MAC(v0, v1, v2, u[44], m[31]);
+	MONT_MAC(w0, w1, w2, u[45], m[30]);
+	MONT_MAC(t0, t1, t2, u[46], m[29]);
+	MONT_MAC(v0, v1, v2, u[47], m[28]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[27] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 76 */
+	MONT_MUL(s0, s1, s2, a[29], a[47]);
+	MONT_MUL(c0, c1, c2, a[30], a[46]);
+	MONT_MAC(s0, s1, s2, a[31], a[45]);
+	MONT_MAC(c0, c1, c2, a[32], a[44]);
+	MONT_MAC(s0, s1, s2, a[33], a[43]);
+	MONT_MAC(c0, c1, c2, a[34], a[42]);
+	MONT_MAC(s0, s1, s2, a[35], a[41]);
+	MONT_MAC(c0, c1, c2, a[36], a[40]);
+	MONT_MAC(s0, s1, s2, a[37], a[39]);
+	MONT_MAC(t0, t1, t2, a[38], a[38]);
+	MONT_MUL(v0, v1, v2, u[29], m[47]);
+	MONT_MUL(w0, w1, w2, u[30], m[46]);
+	MONT_MAC(t0, t1, t2, u[31], m[45]);
+	MONT_MAC(v0, v1, v2, u[32], m[44]);
+	MONT_MAC(w0, w1, w2, u[33], m[43]);
+	MONT_MAC(t0, t1, t2, u[34], m[42]);
+	MONT_MAC(v0, v1, v2, u[35], m[41]);
+	MONT_MAC(w0, w1, w2, u[36], m[40]);
+	MONT_MAC(t0, t1, t2, u[37], m[39]);
+	MONT_MAC(v0, v1, v2, u[38], m[38]);
+	MONT_MAC(w0, w1, w2, u[39], m[37]);
+	MONT_MAC(t0, t1, t2, u[40], m[36]);
+	MONT_MAC(v0, v1, v2, u[41], m[35]);
+	MONT_MAC(w0, w1, w2, u[42], m[34]);
+	MONT_MAC(t0, t1, t2, u[43], m[33]);
+	MONT_MAC(v0, v1, v2, u[44], m[32]);
+	MONT_MAC(w0, w1, w2, u[45], m[31]);
+	MONT_MAC(t0, t1, t2, u[46], m[30]);
+	MONT_MAC(v0, v1, v2, u[47], m[29]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[28] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 77 */
+	MONT_MUL(s0, s1, s2, a[30], a[47]);
+	MONT_MUL(c0, c1, c2, a[31], a[46]);
+	MONT_MAC(s0, s1, s2, a[32], a[45]);
+	MONT_MAC(c0, c1, c2, a[33], a[44]);
+	MONT_MAC(s0, s1, s2, a[34], a[43]);
+	MONT_MAC(c0, c1, c2, a[35], a[42]);
+	MONT_MAC(s0, s1, s2, a[36], a[41]);
+	MONT_MAC(c0, c1, c2, a[37], a[40]);
+	MONT_MAC(s0, s1, s2, a[38], a[39]);
+	MONT_MAC(t0, t1, t2, u[30], m[47]);
+	MONT_MUL(v0, v1, v2, u[31], m[46]);
+	MONT_MUL(w0, w1, w2, u[32], m[45]);
+	MONT_MAC(t0, t1, t2, u[33], m[44]);
+	MONT_MAC(v0, v1, v2, u[34], m[43]);
+	MONT_MAC(w0, w1, w2, u[35], m[42]);
+	MONT_MAC(t0, t1, t2, u[36], m[41]);
+	MONT_MAC(v0, v1, v2, u[37], m[40]);
+	MONT_MAC(w0, w1, w2, u[38], m[39]);
+	MONT_MAC(t0, t1, t2, u[39], m[38]);
+	MONT_MAC(v0, v1, v2, u[40], m[37]);
+	MONT_MAC(w0, w1, w2, u[41], m[36]);
+	MONT_MAC(t0, t1, t2, u[42], m[35]);
+	MONT_MAC(v0, v1, v2, u[43], m[34]);
+	MONT_MAC(w0, w1, w2, u[44], m[33]);
+	MONT_MAC(t0, t1, t2, u[45], m[32]);
+	MONT_MAC(v0, v1, v2, u[46], m[31]);
+	MONT_MAC(w0, w1, w2, u[47], m[30]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[29] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 78 */
+	MONT_MUL(s0, s1, s2, a[31], a[47]);
+	MONT_MUL(c0, c1, c2, a[32], a[46]);
+	MONT_MAC(s0, s1, s2, a[33], a[45]);
+	MONT_MAC(c0, c1, c2, a[34], a[44]);
+	MONT_MAC(s0, s1, s2, a[35], a[43]);
+	MONT_MAC(c0, c1, c2, a[36], a[42]);
+	MONT_MAC(s0, s1, s2, a[37], a[41]);
+	MONT_MAC(c0, c1, c2, a[38], a[40]);
+	MONT_MAC(t0, t1, t2, a[39], a[39]);
+	MONT_MUL(v0, v1, v2, u[31], m[47]);
+	MONT_MUL(w0, w1, w2, u[32], m[46]);
+	MONT_MAC(t0, t1, t2, u[33], m[45]);
+	MONT_MAC(v0, v1, v2, u[34], m[44]);
+	MONT_MAC(w0, w1, w2, u[35], m[43]);
+	MONT_MAC(t0, t1, t2, u[36], m[42]);
+	MONT_MAC(v0, v1, v2, u[37], m[41]);
+	MONT_MAC(w0, w1, w2, u[38], m[40]);
+	MONT_MAC(t0, t1, t2, u[39], m[39]);
+	MONT_MAC(v0, v1, v2, u[40], m[38]);
+	MONT_MAC(w0, w1, w2, u[41], m[37]);
+	MONT_MAC(t0, t1, t2, u[42], m[36]);
+	MONT_MAC(v0, v1, v2, u[43], m[35]);
+	MONT_MAC(w0, w1, w2, u[44], m[34]);
+	MONT_MAC(t0, t1, t2, u[45], m[33]);
+	MONT_MAC(v0, v1, v2, u[46], m[32]);
+	MONT_MAC(w0, w1, w2, u[47], m[31]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[30] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 79 */
+	MONT_MUL(s0, s1, s2, a[32], a[47]);
+	MONT_MUL(c0, c1, c2, a[33], a[46]);
+	MONT_MAC(s0, s1, s2, a[34], a[45]);
+	MONT_MAC(c0, c1, c2, a[35], a[44]);
+	MONT_MAC(s0, s1, s2, a[36], a[43]);
+	MONT_MAC(c0, c1, c2, a[37], a[42]);
+	MONT_MAC(s0, s1, s2, a[38], a[41]);
+	MONT_MAC(c0, c1, c2, a[39], a[40]);
+	MONT_MAC(t0, t1, t2, u[32], m[47]);
+	MONT_MUL(v0, v1, v2, u[33], m[46]);
+	MONT_MUL(w0, w1, w2, u[34], m[45]);
+	MONT_MAC(t0, t1, t2, u[35], m[44]);
+	MONT_MAC(v0, v1, v2, u[36], m[43]);
+	MONT_MAC(w0, w1, w2, u[37], m[42]);
+	MONT_MAC(t0, t1, t2, u[38], m[41]);
+	MONT_MAC(v0, v1, v2, u[39], m[40]);
+	MONT_MAC(w0, w1, w2, u[40], m[39]);
+	MONT_MAC(t0, t1, t2, u[41], m[38]);
+	MONT_MAC(v0, v1, v2, u[42], m[37]);
+	MONT_MAC(w0, w1, w2, u[43], m[36]);
+	MONT_MAC(t0, t1, t2, u[44], m[35]);
+	MONT_MAC(v0, v1, v2, u[45], m[34]);
+	MONT_MAC(w0, w1, w2, u[46], m[33]);
+	MONT_MAC(t0, t1, t2, u[47], m[32]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[31] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 80 */
+	MONT_MUL(s0, s1, s2, a[33], a[47]);
+	MONT_MUL(c0, c1, c2, a[34], a[46]);
+	MONT_MAC(s0, s1, s2, a[35], a[45]);
+	MONT_MAC(c0, c1, c2, a[36], a[44]);
+	MONT_MAC(s0, s1, s2, a[37], a[43]);
+	MONT_MAC(c0, c1, c2, a[38], a[42]);
+	MONT_MAC(s0, s1, s2, a[39], a[41]);
+	MONT_MAC(t0, t1, t2, a[40], a[40]);
+	MONT_MUL(v0, v1, v2, u[33], m[47]);
+	MONT_MUL(w0, w1, w2, u[34], m[46]);
+	MONT_MAC(t0, t1, t2, u[35], m[45]);
+	MONT_MAC(v0, v1, v2, u[36], m[44]);
+	MONT_MAC(w0, w1, w2, u[37], m[43]);
+	MONT_MAC(t0, t1, t2, u[38], m[42]);
+	MONT_MAC(v0, v1, v2, u[39], m[41]);
+	MONT_MAC(w0, w1, w2, u[40], m[40]);
+	MONT_MAC(t0, t1, t2, u[41], m[39]);
+	MONT_MAC(v0, v1, v2, u[42], m[38]);
+	MONT_MAC(w0, w1, w2, u[43], m[37]);
+	MONT_MAC(t0, t1, t2, u[44], m[36]);
+	MONT_MAC(v0, v1, v2, u[45], m[35]);
+	MONT_MAC(w0, w1, w2, u[46], m[34]);
+	MONT_MAC(t0, t1, t2, u[47], m[33]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[32] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 81 */
+	MONT_MUL(s0, s1, s2, a[34], a[47]);
+	MONT_MUL(c0, c1, c2, a[35], a[46]);
+	MONT_MAC(s0, s1, s2, a[36], a[45]);
+	MONT_MAC(c0, c1, c2, a[37], a[44]);
+	MONT_MAC(s0, s1, s2, a[38], a[43]);
+	MONT_MAC(c0, c1, c2, a[39], a[42]);
+	MONT_MAC(s0, s1, s2, a[40], a[41]);
+	MONT_MAC(t0, t1, t2, u[34], m[47]);
+	MONT_MUL(v0, v1, v2, u[35], m[46]);
+	MONT_MUL(w0, w1, w2, u[36], m[45]);
+	MONT_MAC(t0, t1, t2, u[37], m[44]);
+	MONT_MAC(v0, v1, v2, u[38], m[43]);
+	MONT_MAC(w0, w1, w2, u[39], m[42]);
+	MONT_MAC(t0, t1, t2, u[40], m[41]);
+	MONT_MAC(v0, v1, v2, u[41], m[40]);
+	MONT_MAC(w0, w1, w2, u[42], m[39]);
+	MONT_MAC(t0, t1, t2, u[43], m[38]);
+	MONT_MAC(v0, v1, v2, u[44], m[37]);
+	MONT_MAC(w0, w1, w2, u[45], m[36]);
+	MONT_MAC(t0, t1, t2, u[46], m[35]);
+	MONT_MAC(v0, v1, v2, u[47], m[34]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[33] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 82 */
+	MONT_MUL(s0, s1, s2, a[35], a[47]);
+	MONT_MUL(c0, c1, c2, a[36], a[46]);
+	MONT_MAC(s0, s1, s2, a[37], a[45]);
+	MONT_MAC(c0, c1, c2, a[38], a[44]);
+	MONT_MAC(s0, s1, s2, a[39], a[43]);
+	MONT_MAC(c0, c1, c2, a[40], a[42]);
+	MONT_MAC(t0, t1, t2, a[41], a[41]);
+	MONT_MUL(v0, v1, v2, u[35], m[47]);
+	MONT_MUL(w0, w1, w2, u[36], m[46]);
+	MONT_MAC(t0, t1, t2, u[37], m[45]);
+	MONT_MAC(v0, v1, v2, u[38], m[44]);
+	MONT_MAC(w0, w1, w2, u[39], m[43]);
+	MONT_MAC(t0, t1, t2, u[40], m[42]);
+	MONT_MAC(v0, v1, v2, u[41], m[41]);
+	MONT_MAC(w0, w1, w2, u[42], m[40]);
+	MONT_MAC(t0, t1, t2, u[43], m[39]);
+	MONT_MAC(v0, v1, v2, u[44], m[38]);
+	MONT_MAC(w0, w1, w2, u[45], m[37]);
+	MONT_MAC(t0, t1, t2, u[46], m[36]);
+	MONT_MAC(v0, v1, v2, u[47], m[35]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[34] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 83 */
+	MONT_MUL(s0, s1, s2, a[36], a[47]);
+	MONT_MUL(c0, c1, c2, a[37], a[46]);
+	MONT_MAC(s0, s1, s2, a[38], a[45]);
+	MONT_MAC(c0, c1, c2, a[39], a[44]);
+	MONT_MAC(s0, s1, s2, a[40], a[43]);
+	MONT_MAC(c0, c1, c2, a[41], a[42]);
+	MONT_MAC(t0, t1, t2, u[36], m[47]);
+	MONT_MUL(v0, v1, v2, u[37], m[46]);
+	MONT_MUL(w0, w1, w2, u[38], m[45]);
+	MONT_MAC(t0, t1, t2, u[39], m[44]);
+	MONT_MAC(v0, v1, v2, u[40], m[43]);
+	MONT_MAC(w0, w1, w2, u[41], m[42]);
+	MONT_MAC(t0, t1, t2, u[42], m[41]);
+	MONT_MAC(v0, v1, v2, u[43], m[40]);
+	MONT_MAC(w0, w1, w2, u[44], m[39]);
+	MONT_MAC(t0, t1, t2, u[45], m[38]);
+	MONT_MAC(v0, v1, v2, u[46], m[37]);
+	MONT_MAC(w0, w1, w2, u[47], m[36]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[35] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 84 */
+	MONT_MUL(s0, s1, s2, a[37], a[47]);
+	MONT_MUL(c0, c1, c2, a[38], a[46]);
+	MONT_MAC(s0, s1, s2, a[39], a[45]);
+	MONT_MAC(c0, c1, c2, a[40], a[44]);
+	MONT_MAC(s0, s1, s2, a[41], a[43]);
+	MONT_MAC(t0, t1, t2, a[42], a[42]);
+	MONT_MUL(v0, v1, v2, u[37], m[47]);
+	MONT_MUL(w0, w1, w2, u[38], m[46]);
+	MONT_MAC(t0, t1, t2, u[39], m[45]);
+	MONT_MAC(v0, v1, v2, u[40], m[44]);
+	MONT_MAC(w0, w1, w2, u[41], m[43]);
+	MONT_MAC(t0, t1, t2, u[42], m[42]);
+	MONT_MAC(v0, v1, v2, u[43], m[41]);
+	MONT_MAC(w0, w1, w2, u[44], m[40]);
+	MONT_MAC(t0, t1, t2, u[45], m[39]);
+	MONT_MAC(v0, v1, v2, u[46], m[38]);
+	MONT_MAC(w0, w1, w2, u[47], m[37]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[36] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 85 */
+	MONT_MUL(s0, s1, s2, a[38], a[47]);
+	MONT_MUL(c0, c1, c2, a[39], a[46]);
+	MONT_MAC(s0, s1, s2, a[40], a[45]);
+	MONT_MAC(c0, c1, c2, a[41], a[44]);
+	MONT_MAC(s0, s1, s2, a[42], a[43]);
+	MONT_MAC(t0, t1, t2, u[38], m[47]);
+	MONT_MUL(v0, v1, v2, u[39], m[46]);
+	MONT_MUL(w0, w1, w2, u[40], m[45]);
+	MONT_MAC(t0, t1, t2, u[41], m[44]);
+	MONT_MAC(v0, v1, v2, u[42], m[43]);
+	MONT_MAC(w0, w1, w2, u[43], m[42]);
+	MONT_MAC(t0, t1, t2, u[44], m[41]);
+	MONT_MAC(v0, v1, v2, u[45], m[40]);
+	MONT_MAC(w0, w1, w2, u[46], m[39]);
+	MONT_MAC(t0, t1, t2, u[47], m[38]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[37] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 86 */
+	MONT_MUL(s0, s1, s2, a[39], a[47]);
+	MONT_MUL(c0, c1, c2, a[40], a[46]);
+	MONT_MAC(s0, s1, s2, a[41], a[45]);
+	MONT_MAC(c0, c1, c2, a[42], a[44]);
+	MONT_MAC(t0, t1, t2, a[43], a[43]);
+	MONT_MUL(v0, v1, v2, u[39], m[47]);
+	MONT_MUL(w0, w1, w2, u[40], m[46]);
+	MONT_MAC(t0, t1, t2, u[41], m[45]);
+	MONT_MAC(v0, v1, v2, u[42], m[44]);
+	MONT_MAC(w0, w1, w2, u[43], m[43]);
+	MONT_MAC(t0, t1, t2, u[44], m[42]);
+	MONT_MAC(v0, v1, v2, u[45], m[41]);
+	MONT_MAC(w0, w1, w2, u[46], m[40]);
+	MONT_MAC(t0, t1, t2, u[47], m[39]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[38] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 87 */
+	MONT_MUL(s0, s1, s2, a[40], a[47]);
+	MONT_MUL(c0, c1, c2, a[41], a[46]);
+	MONT_MAC(s0, s1, s2, a[42], a[45]);
+	MONT_MAC(c0, c1, c2, a[43], a[44]);
+	MONT_MAC(t0, t1, t2, u[40], m[47]);
+	MONT_MUL(v0, v1, v2, u[41], m[46]);
+	MONT_MUL(w0, w1, w2, u[42], m[45]);
+	MONT_MAC(t0, t1, t2, u[43], m[44]);
+	MONT_MAC(v0, v1, v2, u[44], m[43]);
+	MONT_MAC(w0, w1, w2, u[45], m[42]);
+	MONT_MAC(t0, t1, t2, u[46], m[41]);
+	MONT_MAC(v0, v1, v2, u[47], m[40]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[39] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 88 */
+	MONT_MUL(s0, s1, s2, a[41], a[47]);
+	MONT_MUL(c0, c1, c2, a[42], a[46]);
+	MONT_MAC(s0, s1, s2, a[43], a[45]);
+	MONT_MAC(t0, t1, t2, a[44], a[44]);
+	MONT_MUL(v0, v1, v2, u[41], m[47]);
+	MONT_MUL(w0, w1, w2, u[42], m[46]);
+	MONT_MAC(t0, t1, t2, u[43], m[45]);
+	MONT_MAC(v0, v1, v2, u[44], m[44]);
+	MONT_MAC(w0, w1, w2, u[45], m[43]);
+	MONT_MAC(t0, t1, t2, u[46], m[42]);
+	MONT_MAC(v0, v1, v2, u[47], m[41]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[40] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 89 */
+	MONT_MUL(s0, s1, s2, a[42], a[47]);
+	MONT_MUL(c0, c1, c2, a[43], a[46]);
+	MONT_MAC(s0, s1, s2, a[44], a[45]);
+	MONT_MAC(t0, t1, t2, u[42], m[47]);
+	MONT_MUL(v0, v1, v2, u[43], m[46]);
+	MONT_MUL(w0, w1, w2, u[44], m[45]);
+	MONT_MAC(t0, t1, t2, u[45], m[44]);
+	MONT_MAC(v0, v1, v2, u[46], m[43]);
+	MONT_MAC(w0, w1, w2, u[47], m[42]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[41] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 90 */
+	MONT_MUL(s0, s1, s2, a[43], a[47]);
+	MONT_MUL(c0, c1, c2, a[44], a[46]);
+	MONT_MAC(t0, t1, t2, a[45], a[45]);
+	MONT_MUL(v0, v1, v2, u[43], m[47]);
+	MONT_MUL(w0, w1, w2, u[44], m[46]);
+	MONT_MAC(t0, t1, t2, u[45], m[45]);
+	MONT_MAC(v0, v1, v2, u[46], m[44]);
+	MONT_MAC(w0, w1, w2, u[47], m[43]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[42] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 91 */
+	MONT_MUL(s0, s1, s2, a[44], a[47]);
+	MONT_MUL(c0, c1, c2, a[45], a[46]);
+	MONT_MAC(t0, t1, t2, u[44], m[47]);
+	MONT_MUL(v0, v1, v2, u[45], m[46]);
+	MONT_MUL(w0, w1, w2, u[46], m[45]);
+	MONT_MAC(t0, t1, t2, u[47], m[44]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_ADD(s0, s1, s2, c0, c1, c2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[43] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 92 */
+	MONT_MUL(s0, s1, s2, a[45], a[47]);
+	MONT_MAC(t0, t1, t2, a[46], a[46]);
+	MONT_MUL(v0, v1, v2, u[45], m[47]);
+	MONT_MUL(w0, w1, w2, u[46], m[46]);
+	MONT_MAC(t0, t1, t2, u[47], m[45]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_ADD(t0, t1, t2, w0, w1, w2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[44] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 93 */
+	MONT_MUL(s0, s1, s2, a[46], a[47]);
+	MONT_MAC(t0, t1, t2, u[46], m[47]);
+	MONT_MUL(v0, v1, v2, u[47], m[46]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	MONT_DBL(s0, s1, s2);
+	MONT_ADD(t0, t1, t2, s0, s1, s2);
+	z[45] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	/* column 94 */
+	MONT_MAC(t0, t1, t2, a[47], a[47]);
+	MONT_MUL(v0, v1, v2, u[47], m[47]);
+	MONT_ADD(t0, t1, t2, v0, v1, v2);
+	z[46] = t0;
+	t0 = t1;
+	t1 = t2;
+	t2 = 0;
+	z[47] = t0;
+
+	/* under 2m, with t1 the bit above n limbs: at most one subtraction */
+	borrow = sub_n(r, z, m, 48);
+	take = t1 | (borrow ^ 1);
+	select_n(r, r, z, take & 1, 48);
 }
 
 #endif
diff --git a/cbits/crypton_mont.py b/cbits/crypton_mont.py
--- a/cbits/crypton_mont.py
+++ b/cbits/crypton_mont.py
@@ -14,13 +14,16 @@
 """
 
 SIZES = (16, 24, 32)
+# Squaring at 48 too, RSA-3072's modulus, for the verification that is
+# seventeen squarings.  Its multiplication, at twice the code, is left out.
+SQR_ONLY = (48,)
 
 HEADER = """\
 /* Generated by cbits/crypton_mont.py; do not edit.
  *
  * Montgomery multiplication and squaring for AArch64 at 16, 24 and 32 limbs,
- * the halves of RSA-2048, -3072 and -4096.  Each answers what mont_mul and
- * mont_sqr answer. */
+ * the halves of RSA-2048, -3072 and -4096, and squaring at 48, RSA-3072's
+ * modulus.  Each answers what mont_mul and mont_sqr answer. */
 #ifndef CRYPTON_MONT_H
 #define CRYPTON_MONT_H
 
@@ -160,6 +163,8 @@
     print(HEADER)
     for n in SIZES:
         print(gen(n, False))
+        print(gen(n, True))
+    for n in SQR_ONLY:
         print(gen(n, True))
     print(FOOTER, end="")
 
diff --git a/cbits/crypton_powm.c b/cbits/crypton_powm.c
--- a/cbits/crypton_powm.c
+++ b/cbits/crypton_powm.c
@@ -59,13 +59,16 @@
 extern void bignum_mul(uint64_t k, uint64_t *z, uint64_t m, const uint64_t *x,
                        uint64_t n, const uint64_t *y);
 extern void bignum_sqr(uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x);
+extern void bignum_sqr_8_16(uint64_t *z, const uint64_t *x);
+extern void bignum_mul_8_16(uint64_t *z, const uint64_t *x, const uint64_t *y);
 
 /* 16 limbs is 1024 bits and 32 is 2048: the halves a CRT exponentiation
  * works in for RSA-2048 and RSA-4096, and the whole thing without CRT.  24
- * is 1536, the half of RSA-3072, which has no Karatsuba routine of its own
- * and is run through the 32-limb one with its operands padded -- a third
- * of that routine's work wasted, and still nearly twice the C, since the C
- * cannot form ADCX and ADOX's two carry chains at any size.
+ * is 1536, the half of RSA-3072, which has no Karatsuba routine of its own:
+ * its multiplication is the 32-limb one with the operands padded, and its
+ * square is built from 8-limb pieces, which measured faster on a whole
+ * exponentiation than the padded square.  Both are still nearly twice the
+ * C, since the C cannot form ADCX and ADOX's two carry chains at any size.
  *
  * 48 and 64 are 3072 and 4096 bits: finite-field Diffie-Hellman over the
  * RFC 7919 groups of those sizes, and RSA without CRT.  There is no
@@ -138,14 +141,39 @@
 	powm_s2n_finish(r, z, m, bignum_emontredc_8n(n, z, m, n0), n);
 }
 
+/* a^2 for a of 24 limbs, from three 8-limb squares and three 8-limb
+ * products: a = a0 + a1 X + a2 X^2 with X = 2^512, and the cross terms, at
+ * X to X^3 in c, go in doubled.  c is 48 limbs of scratch. */
+static void powm_s2n_sqr24(limb_t *z, const limb_t *a, limb_t *c)
+{
+	limb_t k;
+	uint32_t i;
+
+	bignum_sqr_8_16(z, a);
+	bignum_sqr_8_16(z + 16, a + 8);
+	bignum_sqr_8_16(z + 32, a + 16);
+	bignum_mul_8_16(c, a, a + 8);
+	bignum_mul_8_16(c + 16, a + 8, a + 16);
+	bignum_mul_8_16(c + 32, a, a + 16);
+	k = add_n(c + 8, c + 8, c + 32, 16);
+	for (i = 24; i < 32; i++) {
+		c[i] += k;
+		k = c[i] < k;
+	}
+	k = shl1(c, 32);
+	k += add_n(z + 8, z + 8, c, 32);
+	for (i = 40; i < 48; i++) {
+		z[i] += k;
+		k = z[i] < k;
+	}
+}
+
 static void powm_s2n_sqr(limb_t *r, const limb_t *a, const limb_t *m,
                          limb_t n0, uint32_t n, limb_t *z, limb_t *scratch)
 {
 	if (n == 24) {
 		z = scratch + POWM_S2N_PAD_Z;
-		powm_s2n_pad(scratch + POWM_S2N_PAD_X, a);
-		bignum_ksqr_32_64(z, scratch + POWM_S2N_PAD_X,
-		                  scratch + POWM_S2N_PAD_T);
+		powm_s2n_sqr24(z, a, scratch + POWM_S2N_PAD_T);
 	} else if (n == 48 || n == 64)
 		bignum_sqr(2 * n, z, n, a);
 	else if (n == 16)
@@ -203,6 +231,7 @@
 	case 16: crypton_mont_sqr16(r, a, m, n0, t); return;
 	case 24: crypton_mont_sqr24(r, a, m, n0, t); return;
 	case 32: crypton_mont_sqr32(r, a, m, n0, t); return;
+	case 48: crypton_mont_sqr48(r, a, m, n0, t); return;
 	}
 #endif
 	mont_sqr(r, a, m, n0, n, t);
@@ -350,14 +379,8 @@
  * bits; the bound is set well above them and well below where a Diffie-
  * Hellman or DSA exponent starts.
  *
- * The second is a machine where s2n-bignum's Montgomery multiplication does
- * not run.  There the multiplication here is the C one, which is not faster
- * than what the caller already has, so there is nothing to take over.  That
- * was written as an expectation and has since been measured: on an Apple
- * M4, verification through here and through GMP come out level, the
- * difference no larger than between two rows neither of them touches.
- * The third is every size but 2048 bits, where the assembly runs and GMP is
- * faster all the same; see powm_pub_wanted.
+ * The second and third are a machine and a size where GMP, which the
+ * caller has, was measured the faster; see powm_pub_wanted.
  *
  * Define CRYPTON_POWM_PUB_ALWAYS to make it accept anyway: the differential
  * test builds that way, so that this arithmetic is exercised on the
@@ -380,9 +403,15 @@
 #elif defined(CRYPTON_POWM_S2N)
 	return n == 32 && powm_s2n_usable(n);
 #elif defined(CRYPTON_MONT_FIXED)
-	/* AArch64: the generated code is ahead of GMP at 2048 bits, and the
-	 * Linux GMP is ahead of the C at 3072 and 4096 */
+	/* AArch64: the generated code is ahead of GMP at 2048 bits.  At the
+	 * other RSA sizes Linux's GMP is level with the C or ahead of it.  The
+	 * GMP GHC builds into itself on macOS is compiled without -O, and is
+	 * behind the C from 1024 to 4096 bits on the same M4 */
+#if defined(__APPLE__)
+	return n >= 16 && n <= 64;
+#else
 	return n == 32;
+#endif
 #else
 	(void) n;
 	return 0;
diff --git a/cbits/s2n/README.md b/cbits/s2n/README.md
--- a/cbits/s2n/README.md
+++ b/cbits/s2n/README.md
@@ -53,7 +53,8 @@
 `crypton_powm.c`'s modular exponentiation also borrows from here, but only its
 innermost step and only on x86-64: `bignum_kmul_16_32`, `bignum_ksqr_16_32`,
 `bignum_kmul_32_64`, `bignum_ksqr_32_64` and `bignum_emontredc_8n` replace the
-C's Montgomery multiplication and square.  The window, the table and its masked
+C's Montgomery multiplication and square, and at RSA-3072's 24 limbs the square
+is built from `bignum_sqr_8_16` and `bignum_mul_8_16`.  The window, the table and its masked
 scan are crypton's throughout.  Sixteen limbs is 1024 bits and thirty-two is
 2048: the halves a CRT exponentiation works in for RSA-2048 and RSA-4096, and
 the whole thing without CRT.  The reduction wants ADX, so the choice is made at
diff --git a/cbits/s2n/import.sh b/cbits/s2n/import.sh
--- a/cbits/s2n/import.sh
+++ b/cbits/s2n/import.sh
@@ -110,6 +110,10 @@
 take_x86 fastmul bignum_kmul_32_64
 take_x86 fastmul bignum_ksqr_32_64
 take_x86 fastmul bignum_emontredc_8n
+# RSA-3072's 24-limb square, built from these where the 32-limb Karatsuba
+# would take its operands padded
+take_x86 fastmul bignum_sqr_8_16
+take_x86 fastmul bignum_mul_8_16
 # and, for the sizes there is no Karatsuba routine for, the schoolbook
 # multiplication and squaring of any size, which bignum_emontredc_8n then
 # reduces as it reduces the others
diff --git a/cbits/s2n/x86_att/bignum_mul_8_16.S b/cbits/s2n/x86_att/bignum_mul_8_16.S
new file mode 100644
--- /dev/null
+++ b/cbits/s2n/x86_att/bignum_mul_8_16.S
@@ -0,0 +1,264 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[8], y[8]; output z[16]
+//
+//    extern void bignum_mul_8_16(uint64_t z[static 16], const uint64_t x[static 8],
+//                                const uint64_t y[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
+// Microsoft x64 ABI:   RCX = z, RDX = x, R8 = y
+// ----------------------------------------------------------------------------
+
+#include "_internal_s2n_bignum_x86_att.h"
+
+
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_8_16)
+        S2N_BN_FUNCTION_TYPE_DIRECTIVE(bignum_mul_8_16)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_8_16)
+        .text
+
+// These are actually right
+
+#define z %rdi
+#define x %rsi
+
+// Copied in or set up
+
+#define y %rcx
+
+// A zero register
+
+#define zero %rbp
+#define zeroe %ebp
+
+// mulpadd i, j adds x[i] * rdx (now assumed = y[j]) into the window at i+j
+
+.macro mulpadd arg1,arg2
+        mulxq   8*\arg1(x), %rax, %rbx
+.if ((\arg1 + \arg2) % 8 == 0)
+        adcxq   %rax, %r8
+        adoxq   %rbx, %r9
+.elseif ((\arg1 + \arg2) % 8 == 1)
+        adcxq   %rax, %r9
+        adoxq   %rbx, %r10
+.elseif ((\arg1 + \arg2) % 8 == 2)
+        adcxq   %rax, %r10
+        adoxq   %rbx, %r11
+.elseif ((\arg1 + \arg2) % 8 == 3)
+        adcxq   %rax, %r11
+        adoxq   %rbx, %r12
+.elseif ((\arg1 + \arg2) % 8 == 4)
+        adcxq   %rax, %r12
+        adoxq   %rbx, %r13
+.elseif ((\arg1 + \arg2) % 8 == 5)
+        adcxq   %rax, %r13
+        adoxq   %rbx, %r14
+.elseif ((\arg1 + \arg2) % 8 == 6)
+        adcxq   %rax, %r14
+        adoxq   %rbx, %r15
+.elseif ((\arg1 + \arg2) % 8 == 7)
+        adcxq   %rax, %r15
+        adoxq   %rbx, %r8
+.endif
+
+.endm
+
+// mulpade i, j adds x[i] * rdx (now assumed = y[j]) into the window at i+j
+// but re-creates the top word assuming nothing to add there
+
+.macro mulpade arg1,arg2
+.if ((\arg1 + \arg2) % 8 == 0)
+        mulxq   8*\arg1(x), %rax, %r9
+        adcxq   %rax, %r8
+        adoxq   zero, %r9
+.elseif ((\arg1 + \arg2) % 8 == 1)
+        mulxq   8*\arg1(x), %rax, %r10
+        adcxq   %rax, %r9
+        adoxq   zero, %r10
+.elseif ((\arg1 + \arg2) % 8 == 2)
+        mulxq   8*\arg1(x), %rax, %r11
+        adcxq   %rax, %r10
+        adoxq   zero, %r11
+.elseif ((\arg1 + \arg2) % 8 == 3)
+        mulxq   8*\arg1(x), %rax, %r12
+        adcxq   %rax, %r11
+        adoxq   zero, %r12
+.elseif ((\arg1 + \arg2) % 8 == 4)
+        mulxq   8*\arg1(x), %rax, %r13
+        adcxq   %rax, %r12
+        adoxq   zero, %r13
+.elseif ((\arg1 + \arg2) % 8 == 5)
+        mulxq   8*\arg1(x), %rax, %r14
+        adcxq   %rax, %r13
+        adoxq   zero, %r14
+.elseif ((\arg1 + \arg2) % 8 == 6)
+        mulxq   8*\arg1(x), %rax, %r15
+        adcxq   %rax, %r14
+        adoxq   zero, %r15
+.elseif ((\arg1 + \arg2) % 8 == 7)
+        mulxq   8*\arg1(x), %rax, %r8
+        adcxq   %rax, %r15
+        adoxq   zero, %r8
+.endif
+
+.endm
+
+// Add in the whole j'th row
+
+.macro addrow arg1
+        movq    8*\arg1(y), %rdx
+        xorl    zeroe, zeroe
+
+        mulpadd 0, \arg1
+
+.if (\arg1 % 8 == 0)
+        movq    %r8, 8*\arg1(z)
+.elseif (\arg1 % 8 == 1)
+        movq    %r9, 8*\arg1(z)
+.elseif (\arg1 % 8 == 2)
+        movq    %r10, 8*\arg1(z)
+.elseif (\arg1 % 8 == 3)
+        movq    %r11, 8*\arg1(z)
+.elseif (\arg1 % 8 == 4)
+        movq    %r12, 8*\arg1(z)
+.elseif (\arg1 % 8 == 5)
+        movq    %r13, 8*\arg1(z)
+.elseif (\arg1 % 8 == 6)
+        movq    %r14, 8*\arg1(z)
+.elseif (\arg1 % 8 == 7)
+        movq    %r15, 8*\arg1(z)
+.endif
+
+        mulpadd 1, \arg1
+        mulpadd 2, \arg1
+        mulpadd 3, \arg1
+        mulpadd 4, \arg1
+        mulpadd 5, \arg1
+        mulpadd 6, \arg1
+        mulpade 7, \arg1
+
+.if (\arg1 % 8 == 0)
+        adcq    zero, %r8
+.elseif (\arg1 % 8 == 1)
+        adcq    zero, %r9
+.elseif (\arg1 % 8 == 2)
+        adcq    zero, %r10
+.elseif (\arg1 % 8 == 3)
+        adcq    zero, %r11
+.elseif (\arg1 % 8 == 4)
+        adcq    zero, %r12
+.elseif (\arg1 % 8 == 5)
+        adcq    zero, %r13
+.elseif (\arg1 % 8 == 6)
+        adcq    zero, %r14
+.elseif (\arg1 % 8 == 7)
+        adcq    zero, %r15
+.endif
+
+.endm
+
+
+S2N_BN_SYMBOL(bignum_mul_8_16):
+        CFI_START
+        _CET_ENDBR
+
+#if WINDOWS_ABI
+        CFI_PUSH(%rdi)
+        CFI_PUSH(%rsi)
+        movq    %rcx, %rdi
+        movq    %rdx, %rsi
+        movq    %r8, %rdx
+#endif
+
+// Save more registers to play with
+
+        CFI_PUSH(%rbp)
+        CFI_PUSH(%rbx)
+        CFI_PUSH(%r12)
+        CFI_PUSH(%r13)
+        CFI_PUSH(%r14)
+        CFI_PUSH(%r15)
+
+// Copy y into a safe register to start with
+
+        movq    %rdx, y
+
+// Zero a register, which also makes sure we don't get a fake carry-in
+
+        xorl    zeroe, zeroe
+
+// Do the zeroth row, which is a bit different
+// Write back the zero-zero product and then accumulate
+// %r8,%r15,%r14,%r13,%r12,%r11,%r10,%r9 as y[0] * x from 1..8
+
+        movq    (y), %rdx
+
+        mulxq   (x), %r8, %r9
+        movq    %r8, (z)
+
+        mulxq   8(x), %rbx, %r10
+        adcq    %rbx, %r9
+
+        mulxq   16(x), %rbx, %r11
+        adcq    %rbx, %r10
+
+        mulxq   24(x), %rbx, %r12
+        adcq    %rbx, %r11
+
+        mulxq   32(x), %rbx, %r13
+        adcq    %rbx, %r12
+
+        mulxq   40(x), %rbx, %r14
+        adcq    %rbx, %r13
+
+        mulxq   48(x), %rbx, %r15
+        adcq    %rbx, %r14
+
+        mulxq   56(x), %rbx, %r8
+        adcq    %rbx, %r15
+        adcq    zero, %r8
+
+// Now all the other rows in a uniform pattern
+
+        addrow  1
+        addrow  2
+        addrow  3
+        addrow  4
+        addrow  5
+        addrow  6
+        addrow  7
+
+// Now write back the additional columns
+
+        movq    %r8, 64(z)
+        movq    %r9, 72(z)
+        movq    %r10, 80(z)
+        movq    %r11, 88(z)
+        movq    %r12, 96(z)
+        movq    %r13, 104(z)
+        movq    %r14, 112(z)
+        movq    %r15, 120(z)
+
+// Real epilog
+
+        CFI_POP(%r15)
+        CFI_POP(%r14)
+        CFI_POP(%r13)
+        CFI_POP(%r12)
+        CFI_POP(%rbx)
+        CFI_POP(%rbp)
+
+#if WINDOWS_ABI
+        CFI_POP(%rsi)
+        CFI_POP(%rdi)
+#endif
+        CFI_RET
+
+S2N_BN_SIZE_DIRECTIVE(bignum_mul_8_16)
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/cbits/s2n/x86_att/bignum_sqr_8_16.S b/cbits/s2n/x86_att/bignum_sqr_8_16.S
new file mode 100644
--- /dev/null
+++ b/cbits/s2n/x86_att/bignum_sqr_8_16.S
@@ -0,0 +1,302 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0
+
+// ----------------------------------------------------------------------------
+// Square, z := x^2
+// Input x[8]; output z[16]
+//
+//    extern void bignum_sqr_8_16(uint64_t z[static 16], const uint64_t x[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x
+// Microsoft x64 ABI:   RCX = z, RDX = x
+// ----------------------------------------------------------------------------
+
+#include "_internal_s2n_bignum_x86_att.h"
+
+
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_8_16)
+        S2N_BN_FUNCTION_TYPE_DIRECTIVE(bignum_sqr_8_16)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_8_16)
+        .text
+
+// These are actually right
+
+#define z %rdi
+#define x %rsi
+
+// A zero register
+
+#define zero %rbp
+#define zeroe %ebp
+
+// mulpadd i, j adds rdx * x[i] into the window  at the i+j point
+
+.macro mulpadd arg1,arg2
+        mulxq   8*\arg1(x), %rax, %rcx
+.if ((\arg1 + \arg2) % 8 == 0)
+        adcxq   %rax, %r8
+        adoxq   %rcx, %r9
+.elseif ((\arg1 + \arg2) % 8 == 1)
+        adcxq   %rax, %r9
+        adoxq   %rcx, %r10
+.elseif ((\arg1 + \arg2) % 8 == 2)
+        adcxq   %rax, %r10
+        adoxq   %rcx, %r11
+.elseif ((\arg1 + \arg2) % 8 == 3)
+        adcxq   %rax, %r11
+        adoxq   %rcx, %r12
+.elseif ((\arg1 + \arg2) % 8 == 4)
+        adcxq   %rax, %r12
+        adoxq   %rcx, %r13
+.elseif ((\arg1 + \arg2) % 8 == 5)
+        adcxq   %rax, %r13
+        adoxq   %rcx, %r14
+.elseif ((\arg1 + \arg2) % 8 == 6)
+        adcxq   %rax, %r14
+        adoxq   %rcx, %r15
+.elseif ((\arg1 + \arg2) % 8 == 7)
+        adcxq   %rax, %r15
+        adoxq   %rcx, %r8
+.endif
+
+.endm
+
+// mulpade i, j adds rdx * x[i] into the window at i+j
+// but re-creates the top word assuming nothing to add there
+
+.macro mulpade arg1,arg2
+.if ((\arg1 + \arg2) % 8 == 0)
+        mulxq   8*\arg1(x), %rax, %r9
+        adcxq   %rax, %r8
+        adoxq   zero, %r9
+.elseif ((\arg1 + \arg2) % 8 == 1)
+        mulxq   8*\arg1(x), %rax, %r10
+        adcxq   %rax, %r9
+        adoxq   zero, %r10
+.elseif ((\arg1 + \arg2) % 8 == 2)
+        mulxq   8*\arg1(x), %rax, %r11
+        adcxq   %rax, %r10
+        adoxq   zero, %r11
+.elseif ((\arg1 + \arg2) % 8 == 3)
+        mulxq   8*\arg1(x), %rax, %r12
+        adcxq   %rax, %r11
+        adoxq   zero, %r12
+.elseif ((\arg1 + \arg2) % 8 == 4)
+        mulxq   8*\arg1(x), %rax, %r13
+        adcxq   %rax, %r12
+        adoxq   zero, %r13
+.elseif ((\arg1 + \arg2) % 8 == 5)
+        mulxq   8*\arg1(x), %rax, %r14
+        adcxq   %rax, %r13
+        adoxq   zero, %r14
+.elseif ((\arg1 + \arg2) % 8 == 6)
+        mulxq   8*\arg1(x), %rax, %r15
+        adcxq   %rax, %r14
+        adoxq   zero, %r15
+.elseif ((\arg1 + \arg2) % 8 == 7)
+        mulxq   8*\arg1(x), %rax, %r8
+        adcxq   %rax, %r15
+        adoxq   zero, %r8
+.endif
+
+.endm
+
+.macro diagonals
+
+        xorl    zeroe, zeroe
+
+// Set initial window [%r8..%r10] + 2 wb = 10 + 20 + 30 + 40 + 50 + 60 + 70
+
+        movq    (x), %rdx
+        mulxq   8(x), %r9, %rax
+        movq    %r9, 8(z)
+        mulxq   16(x), %r10, %rcx
+        adcxq   %rax, %r10
+        movq    %r10, 16(z)
+        mulxq   24(x), %r11, %rax
+        adcxq   %rcx, %r11
+        mulxq   32(x), %r12, %rcx
+        adcxq   %rax, %r12
+        mulxq   40(x), %r13, %rax
+        adcxq   %rcx, %r13
+        mulxq   48(x), %r14, %rcx
+        adcxq   %rax, %r14
+        mulxq   56(x), %r15, %r8
+        adcxq   %rcx, %r15
+        adcxq   zero, %r8
+
+// Add in the next diagonal = 21 + 31 + 41 + 51 + 61 + 71 + 54
+
+        xorl    zeroe, zeroe
+        movq    8(x), %rdx
+        mulpadd 2, 1
+        movq    %r11, 24(z)
+        mulpadd 3, 1
+        movq    %r12, 32(z)
+        mulpadd 4, 1
+        mulpadd 5, 1
+        mulpadd 6, 1
+        mulpade 7, 1
+        movq    32(x), %rdx
+        mulpade 5, 4
+        adcxq   zero, %r10
+
+// And the next one = 32 + 42 + 52 + 62 + 72 + 64 + 65
+
+        xorl    zeroe, zeroe
+        movq    16(x), %rdx
+        mulpadd 3, 2
+        movq    %r13, 40(z)
+        mulpadd 4, 2
+        movq    %r14, 48(z)
+        mulpadd 5, 2
+        mulpadd 6, 2
+        mulpadd 7, 2
+        movq    48(x), %rdx
+        mulpade 4, 6
+        mulpade 5, 6
+        adcxq   zero, %r12
+
+// And the final one = 43 + 53 + 63 + 73 + 74 + 75 + 76
+
+        xorl    zeroe, zeroe
+        movq    24(x), %rdx
+        mulpadd 4, 3
+        movq    %r15, 56(z)
+        mulpadd 5, 3
+        movq    %r8, 64(z)
+        mulpadd 6, 3
+        mulpadd 7, 3
+        movq    56(x), %rdx
+        mulpadd 4, 7
+        mulpade 5, 7
+        mulpade 6, 7
+        adcxq   zero, %r14
+
+// Double and add things; use z[1]..z[8] and thereafter the registers
+// %r9..%r15 which haven't been written back yet
+
+        xorl    zeroe, zeroe
+        movq    (x), %rdx
+        mulxq   %rdx, %rax, %rcx
+        movq    %rax, (z)
+        movq    8(z), %rax
+        adcxq   %rax, %rax
+        adoxq   %rcx, %rax
+        movq    %rax, 8(z)
+
+        movq    16(z), %rax
+        movq    8(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %rax, %rax
+        adoxq   %rdx, %rax
+        movq    %rax, 16(z)
+        movq    24(z), %rax
+        adcxq   %rax, %rax
+        adoxq   %rcx, %rax
+        movq    %rax, 24(z)
+
+        movq    32(z), %rax
+        movq    16(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %rax, %rax
+        adoxq   %rdx, %rax
+        movq    %rax, 32(z)
+        movq    40(z), %rax
+        adcxq   %rax, %rax
+        adoxq   %rcx, %rax
+        movq    %rax, 40(z)
+
+        movq    48(z), %rax
+        movq    24(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %rax, %rax
+        adoxq   %rdx, %rax
+        movq    %rax, 48(z)
+        movq    56(z), %rax
+        adcxq   %rax, %rax
+        adoxq   %rcx, %rax
+        movq    %rax, 56(z)
+
+        movq    64(z), %rax
+        movq    32(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %rax, %rax
+        adoxq   %rdx, %rax
+        movq    %rax, 64(z)
+        adcxq   %r9, %r9
+        adoxq   %rcx, %r9
+        movq    %r9, 72(z)
+
+        movq    40(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %r10, %r10
+        adoxq   %rdx, %r10
+        movq    %r10, 80(z)
+        adcxq   %r11, %r11
+        adoxq   %rcx, %r11
+        movq    %r11, 88(z)
+
+        movq    48(x), %rdx
+        mulxq   %rdx, %rdx, %rcx
+        adcxq   %r12, %r12
+        adoxq   %rdx, %r12
+        movq    %r12, 96(z)
+        adcxq   %r13, %r13
+        adoxq   %rcx, %r13
+        movq    %r13, 104(z)
+
+        movq    56(x), %rdx
+        mulxq   %rdx, %rdx, %r15
+        adcxq   %r14, %r14
+        adoxq   %rdx, %r14
+        movq    %r14, 112(z)
+        adcxq   zero, %r15
+        adoxq   zero, %r15
+        movq    %r15, 120(z)
+
+.endm
+
+
+S2N_BN_SYMBOL(bignum_sqr_8_16):
+        CFI_START
+        _CET_ENDBR
+
+#if WINDOWS_ABI
+        CFI_PUSH(%rdi)
+        CFI_PUSH(%rsi)
+        movq    %rcx, %rdi
+        movq    %rdx, %rsi
+#endif
+
+// Save more registers to play with
+
+        CFI_PUSH(%rbp)
+        CFI_PUSH(%r12)
+        CFI_PUSH(%r13)
+        CFI_PUSH(%r14)
+        CFI_PUSH(%r15)
+
+// Do the multiplication
+
+        diagonals
+
+// Real epilog
+
+        CFI_POP(%r15)
+        CFI_POP(%r14)
+        CFI_POP(%r13)
+        CFI_POP(%r12)
+        CFI_POP(%rbp)
+
+#if WINDOWS_ABI
+        CFI_POP(%rsi)
+        CFI_POP(%rdi)
+#endif
+        CFI_RET
+
+S2N_BN_SIZE_DIRECTIVE(bignum_sqr_8_16)
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/cbits/tests/ct/run.sh b/cbits/tests/ct/run.sh
--- a/cbits/tests/ct/run.sh
+++ b/cbits/tests/ct/run.sh
@@ -296,6 +296,7 @@
 			$s2n/bignum_montifier.S $s2n/bignum_emontredc_8n.S
 			$s2n/bignum_kmul_16_32.S $s2n/bignum_ksqr_16_32.S
 			$s2n/bignum_kmul_32_64.S $s2n/bignum_ksqr_32_64.S
+			$s2n/bignum_sqr_8_16.S $s2n/bignum_mul_8_16.S
 			$s2n/bignum_mul.S $s2n/bignum_sqr.S"
 		powm_s2n_inc="-Icbits/s2n/include -DCRYPTON_S2N_BIGNUM
 			-DCRYPTON_CPU_TESTING_ADX -DCT_POWM_COUNT_S2N
diff --git a/crypton.cabal b/crypton.cabal
--- a/crypton.cabal
+++ b/crypton.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               crypton
-version:            2.2.4
+version:            2.2.5
 -- crypton's own code is BSD-3-Clause.  The parts of
 -- cbits/aes/gcm_fused_x86.c that follow picotls's fusion are MIT, and the
 -- vendored s2n-bignum assembly in cbits/s2n is taken under ISC, and the
@@ -408,6 +408,7 @@
         cbits/p256/p256_ec.c
 
     other-modules:
+        Crypto.Number.ModArithmetic.Pub
         Crypto.PubKey.RSA.Blinded.Internal
         Crypto.Cipher.AES.Primitive
         Crypto.Cipher.Blowfish.Primitive
@@ -725,6 +726,8 @@
                     cbits/s2n/x86_att/bignum_kmul_32_64.S
                     cbits/s2n/x86_att/bignum_ksqr_16_32.S
                     cbits/s2n/x86_att/bignum_ksqr_32_64.S
+                    cbits/s2n/x86_att/bignum_sqr_8_16.S
+                    cbits/s2n/x86_att/bignum_mul_8_16.S
 
     -- The PQ Code Package's mlkem-native and mldsa-native, vendored under
     -- cbits/mlkem and cbits/mldsa.  Apache-2.0 OR ISC OR MIT, the same
diff --git a/tests/NumberSpec.hs b/tests/NumberSpec.hs
--- a/tests/NumberSpec.hs
+++ b/tests/NumberSpec.hs
@@ -202,6 +202,14 @@
             forAll (wideOf bytes) $ \e ->
                 forAll (wideOf 128) $ \b ->
                     expSafe b e modulus1024 === expFast b e modulus1024
+    -- the C takes RSA's exponent at these sizes on some machines; plain
+    -- squaring shares no multiplication with it
+    prop "agrees with plain squaring on RSA's exponent at every key size" $
+        forAll (elements [128, 192, 256, 384, 512]) $ \bytes ->
+            forAll (wideOf bytes) $ \m' ->
+                forAll (wideOf bytes) $ \b ->
+                    let m = m' .|. bit (8 * bytes - 1) .|. 1
+                     in expFast b 65537 m === naivePow (b `mod` m) 65537 m
     -- the fast one keeps R^2 for the last few moduli; asking under more of
     -- them than it keeps, round and round, would show one used for another
     it "keeps each modulus' constant to that modulus" $ do
diff --git a/tests/PubKey/MGF1Spec.hs b/tests/PubKey/MGF1Spec.hs
--- a/tests/PubKey/MGF1Spec.hs
+++ b/tests/PubKey/MGF1Spec.hs
@@ -10,7 +10,11 @@
 import Data.ByteString.Char8 ()
 
 import Crypto.Hash
+import qualified Data.ByteArray as BA
+import Crypto.Number.Serialize (i2ospOf_)
 import Crypto.PubKey.MaskGenFunction
+import Test.Hspec.QuickCheck (prop)
+import Test.QuickCheck (choose, forAll)
 
 import Utils
 
@@ -32,5 +36,26 @@
         }
     ]
 
+-- | RFC 8017's definition through the pure hash API, block by block, which
+-- shares nothing with mgf1's in-place contexts or with the one-shot hash.
+reference :: HashAlgorithm a => a -> ByteString -> Int -> ByteString
+reference alg sd len = B.take len $ B.concat [block c | c <- [0 .. blocks - 1]]
+  where
+    blocks = (len + hashDigestSize alg - 1) `div` hashDigestSize alg
+    block c = BA.convert (hashFinalize (hashUpdates (hashInitWith alg) [sd, i2ospOf_ 4 (fromIntegral c)])) :: ByteString
+
 spec :: Spec
-spec = zipWithM_ doMGFTest [katZero ..] vectorsMGF
+spec = do
+    zipWithM_ doMGFTest [katZero ..] vectorsMGF
+    describe "against the definition" $
+        mapM_ agree
+            [ ("SHA1", \s n -> (mgf1 SHA1 s n, reference SHA1 s n))
+            , ("SHA256", \s n -> (mgf1 SHA256 s n, reference SHA256 s n))
+            , ("SHA512", \s n -> (mgf1 SHA512 s n, reference SHA512 s n))
+            , ("SHA3_256", \s n -> (mgf1 SHA3_256 s n, reference SHA3_256 s n))
+            , ("Blake2b_512", \s n -> (mgf1 Blake2b_512 s n, reference Blake2b_512 s n))
+            ]
+  where
+    agree (name, f) = prop name $
+        forAll (arbitraryBSof 0 100) $ \s -> forAll (choose (0, 300)) $ \n ->
+            let (got, want) = f s n in got == (want :: ByteString)
diff --git a/tests/PubKey/RSASpec.hs b/tests/PubKey/RSASpec.hs
--- a/tests/PubKey/RSASpec.hs
+++ b/tests/PubKey/RSASpec.hs
@@ -20,6 +20,7 @@
 import Crypto.PubKey.RSA.Prim (ep)
 import qualified Crypto.PubKey.RSA.Prim as Prim
 import qualified Data.ByteString as B
+import Data.Bits ((.|.))
 import Data.Either
 
 import Imports
@@ -241,6 +242,68 @@
             , os2ip ct + modulus < 2 ^ (8 * k)
             ]
 
+-- | The public-key operation takes bytes to the C and back where it can, and
+-- the 'Integer' path where it cannot: a representative not below the
+-- modulus, or one of another length.  Either way the answer is what plain
+-- squaring gives, which shares nothing with the C.
+publicOperationTests :: Spec
+publicOperationTests = describe "public-key operation" $ do
+    prop "agrees with plain squaring" $
+        forAll (elements [128, 256, 384]) $ \k ->
+            forAll (arbitraryBS k) $ \nb ->
+                forAll (arbitraryBS k) $ \m ->
+                    let pk = keyOf k nb in ep pk m === expected pk m
+    prop "agrees at the edges of the modulus and of the length" $
+        forAll (elements [128, 256, 384]) $ \k ->
+            forAll (arbitraryBS k) $ \nb ->
+                let pk = keyOf k nb
+                    nn = RSA.public_n pk
+                    edges =
+                        [i2ospOf_ k x | x <- [0, 1, nn - 1, nn, nn + 1], x < 2 ^ (8 * k)]
+                            ++ [i2ospOf_ (k - 1) (nn `div` 256), B.cons 0 (i2ospOf_ k (nn - 1))]
+                 in [m | m <- edges, ep pk m /= expected pk m] === []
+  where
+    -- an odd modulus of exactly k bytes, which is all the operation needs
+    keyOf k nb =
+        RSA.PublicKey k (os2ip nb .|. (2 ^ (8 * k - 1)) .|. 1) 0x10001
+    -- b^65537 as b squared sixteen times, times b
+    expected pk m = i2ospOf_ (RSA.public_size pk) (squared 16 b * b `mod` nn) :: ByteString
+      where
+        nn = RSA.public_n pk
+        b = os2ip m `mod` nn
+        squared :: Int -> Integer -> Integer
+        squared 0 x = x
+        squared i x = squared (i - 1) (x * x `mod` nn)
+
+-- | A key whose CRT values are off by one stands in for a fault in one half
+-- of the computation, which would otherwise hand out a signature whose gcd
+-- with n is a prime.  Every private-key path has to answer as the sound key.
+crtFaultTests :: Spec
+crtFaultTests = describe "a fault in one CRT half" $
+    forM_ faults $ \(name, bad) -> describe name $ do
+        it "signs what the sound key signs" $
+            RSA.sign Nothing (Just SHA256) bad m `shouldBe` RSA.sign Nothing (Just SHA256) key m
+        prop "signs with a blinder what the sound key signs" $ \testDRG ->
+            let blinder = withTestDRG testDRG $ RSA.generateBlinder (RSA.public_n pub)
+             in RSA.sign (Just blinder) (Just SHA256) bad m
+                    === RSA.sign Nothing (Just SHA256) key m
+        prop "signs through signSafer what the sound key signs" $ \testDRG ->
+            withTestDRG testDRG (RSA.signSafer (Just SHA256) bad m)
+                === RSA.sign Nothing (Just SHA256) key m
+        it "decrypts what it was given" $ do
+            c <- either (error . show) id <$> RSA.encrypt pub m
+            RSA.decrypt Nothing bad c `shouldBe` (Right m :: Either RSA.Error ByteString)
+  where
+    vector = firstVector vectorsSHA1
+    key = vectorToPrivate vector
+    pub = vectorToPublic vector
+    m = "a message to sign" :: ByteString
+    faults =
+        [ ("dP", key{RSA.private_dP = RSA.private_dP key + 1})
+        , ("dQ", key{RSA.private_dQ = RSA.private_dQ key + 1})
+        , ("qinv", key{RSA.private_qinv = RSA.private_qinv key + 1})
+        ]
+
 -- | Building a key from its two primes has to arrive at the key the vectors
 -- carry -- the private exponent, both of its halves, and the inverse of one
 -- prime modulo the other, which is the part worked out without the extended
@@ -555,3 +618,5 @@
     blindedKeyTests
     unpadTests
     ciphertextRangeTests
+    publicOperationTests
+    crtFaultTests
