crypton 2.2.3 → 2.2.4
raw patch · 25 files changed
+10781/−3968 lines, 25 files
Files
- CHANGELOG.md +18/−0
- Crypto/Number/ModArithmetic.hs +73/−34
- Crypto/PubKey/RSA/Blinded.hs +29/−0
- Crypto/PubKey/RSA/Blinded/Internal.hs +136/−0
- Crypto/PubKey/RSA/OAEP.hs +35/−5
- Crypto/PubKey/RSA/PKCS15.hs +84/−15
- Crypto/PubKey/RSA/PSS.hs +54/−10
- Crypto/PubKey/RSA/Prim.hs +60/−4
- Crypto/System/CPU.hs +8/−1
- cbits/crypton_bitfn.h +0/−17
- cbits/crypton_chacha.c +5/−4
- cbits/crypton_cpu.c +10/−0
- cbits/crypton_cpu.h +3/−0
- cbits/crypton_mont.h +9015/−0
- cbits/crypton_mont.py +168/−0
- cbits/crypton_mont_sqr.h +0/−3751
- cbits/crypton_mont_sqr.py +0/−117
- cbits/crypton_powm.c +55/−8
- cbits/crypton_powm.h +27/−0
- cbits/crypton_powm_ifma.c +187/−0
- cbits/crypton_powm_ifma.h +513/−0
- cbits/crypton_powm_ifma.py +178/−0
- crypton.cabal +6/−2
- tests/NumberSpec.hs +7/−0
- tests/PubKey/RSASpec.hs +110/−0
CHANGELOG.md view
@@ -1,5 +1,23 @@ # CHANGELOG for crypton +## 2.2.4++**New module `Crypto.PubKey.RSA.Blinded`.** A `BlindedKey` carries RSA+blinding from one signature or decryption to the next. The existing+`*Safer` functions use it through a small process-wide table, and+verification keeps R^2 per modulus in another.++* perf(rsa): keep the blinding between operations+ [#335](https://github.com/kazu-yamamoto/crypton/pull/335)+* perf(rsa): a generated Montgomery multiplication for AArch64+ [#336](https://github.com/kazu-yamamoto/crypton/pull/336)+* fix: the C warnings CI reports+ [#337](https://github.com/kazu-yamamoto/crypton/pull/337)+* perf(rsa): both CRT halves at once with AVX-512 IFMA+ [#338](https://github.com/kazu-yamamoto/crypton/pull/338)+* perf(rsa): keep R^2 per modulus for verification+ [#339](https://github.com/kazu-yamamoto/crypton/pull/339)+ ## 2.2.3 **crypton builds on Windows again.** 2.2.2's tarball lacked a header that
Crypto/Number/ModArithmetic.hs view
@@ -49,6 +49,9 @@ 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@@ -141,19 +144,6 @@ -- what GMP's own secure exponentiation lets slip !eLen = 8 * ((numBytes e + 7) `div` 8) --- 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"- c_powm_pub- :: Ptr Word8- -> Ptr Word8- -> Word32- -> Ptr Word8- -> Word32- -> Ptr Word8- -> Word32- -> IO CInt foreign import ccall safe "crypton_powm_sec" c_powm_sec@@ -203,31 +193,80 @@ -- 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 $- 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 <-- c_powm_pub- out- base- (fromIntegral mLen)- expo- (fromIntegral eLen)- modu- (fromIntegral mLen)- if r == 0- then do- !v <- Internal.os2ip out mLen- return (Just v)- else return Nothing- _ -> return Nothing+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.
+ Crypto/PubKey/RSA/Blinded.hs view
@@ -0,0 +1,29 @@+-- |+-- Module : Crypto.PubKey.RSA.Blinded+-- License : BSD-style+-- Stability : experimental+-- Portability : Good+--+-- An RSA private key that keeps its blinding between operations.+--+-- Blinding hides the private-key operation's input from timing: it is+-- multiplied by @r^e@ for a random @r@ first, and the result by @r^-1@+-- after. Drawing a new @r@ costs a modular inverse and an exponentiation,+-- about a tenth of an RSA-2048 signature. A t'BlindedKey' draws one and+-- squares the pair for each use after it, which is what OpenSSL does, and+-- draws a new one every 32 uses, from the 'Crypto.Random.Types.MonadRandom'+-- the operation runs in.+--+-- The key is threaded through the operations as a hash context is: each+-- function in "Crypto.PubKey.RSA.PKCS15", "Crypto.PubKey.RSA.PSS" and+-- "Crypto.PubKey.RSA.OAEP" whose name ends in @Blinded@ returns the key for+-- the next one. The @Safer@ functions there keep a t'BlindedKey' per key+-- themselves, for the last few keys used, so they get the same saving+-- without one being passed.+module Crypto.PubKey.RSA.Blinded (+ BlindedKey,+ blindedKey,+ blindedPrivateKey,+) where++import Crypto.PubKey.RSA.Blinded.Internal
+ Crypto/PubKey/RSA/Blinded/Internal.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-cse -fno-full-laziness #-}++-- |+-- Module : Crypto.PubKey.RSA.Blinded.Internal+-- License : BSD-style+-- Stability : experimental+-- Portability : Good+--+-- A private key with a blinding pair that is reused by squaring, as OpenSSL+-- does, rather than generated afresh for every operation. The key is a value+-- threaded through the operations, as a hash 'Crypto.Hash.Context' is.+module Crypto.PubKey.RSA.Blinded.Internal (+ BlindedKey (..),+ blindedKey,+ dpBlinded,+ Draw,+ drawFor,+ withBlindingFor,+ dpWithPair,+) where++import Data.IORef+import System.IO.Unsafe (unsafePerformIO)++import Crypto.Internal.ByteArray (ByteArray, ScrubbedBytes)+import Crypto.Number.Generate (generateMax)+import Crypto.Number.ModArithmetic (expFast, inverseCoprimes)+import Crypto.Number.Serialize (i2ospOf_, os2ip)+import Crypto.PubKey.RSA.Prim (dp)+import Crypto.PubKey.RSA.Types+import Crypto.Random.Types++-- | A private key together with the blinding its next operation uses.+--+-- Each operation multiplies the input by @r^e@ and the output by @r^-1@, and+-- returns the key with both squared for the next one, so a pair costs two+-- multiplications after the first. A new @r@ is drawn every 32 operations.+-- Use the key an operation returns: handing the same one to two operations+-- gives both the same pair.+data BlindedKey = BlindedKey+ { blindedPrivateKey :: PrivateKey+ -- ^ the key it was made from+ , blindedPair :: Pair+ }++-- | @r^e@ and @r^-1@ modulo n, and how many more uses they have after this.+data Pair = Pair !Int !Integer !Integer | Spent++-- | Uses of one @r@ before another is drawn, OpenSSL's number.+refresh :: Int+refresh = 32++-- | A t'BlindedKey' for a private key. The first pair is drawn when it is+-- first used.+blindedKey :: PrivateKey -> BlindedKey+blindedKey pk = BlindedKey pk Spent++-- | The random numbers a new pair is made from: drawing them is cheap, and+-- making the pair, an inverse and an exponentiation, is done only if needed.+data Draw = Draw !Integer !Integer++-- | Draw for a key, as 'Crypto.PubKey.RSA.generateBlinder' does.+drawFor :: forall m. MonadRandom m => PrivateKey -> m Draw+drawFor pk = do+ r <- generateMax (private_n pk)+ u <- os2ip <$> (getRandomBytes 16 :: m ScrubbedBytes)+ return (Draw r u)++-- | @r^e@ and @r^-1@. The inverse is taken of @r*u@ and multiplied by @u@,+-- so the extended Euclidean algorithm never sees @r@, as in+-- 'Crypto.PubKey.RSA.generateBlinder'.+makePair :: PrivateKey -> Draw -> (Integer, Integer)+makePair pk (Draw r u) =+ (expFast r (private_e pk) n, (inverseCoprimes ((r * u) `mod` n) n * u) `mod` n)+ where+ n = private_n pk++-- | The pair for this operation, and the key holding the next one. The+-- draw is used only when a new pair is due.+takePair :: Draw -> BlindedKey -> ((Integer, Integer), BlindedKey)+takePair d (BlindedKey pk pair) = case pair of+ Pair k a ai -> ((a, ai), BlindedKey pk (next k a ai))+ Spent -> case makePair pk d of+ (a, ai) -> ((a, ai), BlindedKey pk (next refresh a ai))+ where+ n = private_n pk+ next k a ai+ | k > 1 = Pair (k - 1) ((a * a) `mod` n) ((ai * ai) `mod` n)+ | otherwise = Spent++-- | The decryption primitive, blinded with a given pair.+dpWithPair :: ByteArray ba => (Integer, Integer) -> PrivateKey -> ba -> ba+dpWithPair (a, ai) pk c = i2ospOf_ k ((ai * os2ip m) `mod` n)+ where+ n = private_n pk+ k = private_size pk+ m = dp Nothing pk (i2ospOf_ k ((a * os2ip c) `mod` n) `asTypeOf` c)++-- | The decryption primitive, blinded with the key's pair, and the key for+-- the next operation. Randomness is drawn only when a new pair is due.+dpBlinded+ :: (MonadRandom m, ByteArray ba) => BlindedKey -> ba -> m (ba, BlindedKey)+dpBlinded bk c = do+ d <- case blindedPair bk of+ Pair {} -> return (Draw 0 0)+ Spent -> drawFor (blindedPrivateKey bk)+ let (pair, bk') = takePair d bk+ return (dpWithPair pair (blindedPrivateKey bk) c, bk')++-- | Run an operation with the pair kept for a key, for the functions that+-- take a bare t'PrivateKey'. One t'BlindedKey' is kept per public key, for+-- the last few keys used; taking its pair and leaving the next is atomic, so+-- no two operations get the same pair. The caller draws every time, since+-- whether a new pair is due is known only in here.+withBlindingFor :: PrivateKey -> Draw -> ((Integer, Integer) -> a) -> a+withBlindingFor pk d f = unsafePerformIO $ do+ pair <- atomicModifyIORef' table step+ return (f pair)+ where+ pub = private_pub pk+ step ks = case break ((== pub) . private_pub . blindedPrivateKey) ks of+ (before, bk : after) -> found bk (before ++ after)+ _ -> found (blindedKey pk) ks+ found bk rest = case takePair d bk of+ (pair@(!_, !_), bk') -> (take tableSize (bk' : rest), pair)+{-# NOINLINE withBlindingFor #-}++-- | How many keys 'withBlindingFor' remembers.+tableSize :: Int+tableSize = 4++table :: IORef [BlindedKey]+table = unsafePerformIO (newIORef [])+{-# NOINLINE table #-}
Crypto/PubKey/RSA/OAEP.hs view
@@ -18,13 +18,14 @@ -- * OAEP decryption decrypt, decryptSafer,+ decryptBlinded, ) where import Crypto.Hash import Crypto.Number.Serialize (os2ip) import Crypto.PubKey.Internal (and') import Crypto.PubKey.MaskGenFunction-import Crypto.PubKey.RSA (generateBlinder)+import Crypto.PubKey.RSA.Blinded.Internal import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.Random.Types@@ -212,7 +213,8 @@ k = private_size pk hashLen = hashDigestSize (oaepHash oaep) --- | Decrypt a ciphertext using OAEP and by automatically generating a blinder.+-- | Decrypt a ciphertext using OAEP, blinded with the pair kept for this key;+-- see "Crypto.PubKey.RSA.Blinded". decryptSafer :: (HashAlgorithm hash, MonadRandom m) => OAEPParams hash ByteString ByteString@@ -222,6 +224,34 @@ -> ByteString -- ^ Cipher text -> m (Either Error ByteString)-decryptSafer oaep pk cipher = do- blinder <- generateBlinder (private_n pk)- return (decrypt (Just blinder) oaep pk cipher)+decryptSafer oaep pk cipher+ | B.length cipher /= k = return (Left MessageSizeIncorrect)+ | os2ip cipher >= private_n pk = return (Left MessageSizeIncorrect)+ | k < 2 * hashLen + 2 = return (Left InvalidParameters)+ | otherwise = do+ d <- drawFor pk+ return $ withBlindingFor pk d $ \pair -> unpad oaep k (dpWithPair pair pk cipher)+ where+ k = private_size pk+ hashLen = hashDigestSize (oaepHash oaep)++-- | 'decrypt' with the blinding a t'BlindedKey' keeps, and the key for the+-- next operation.+decryptBlinded+ :: (HashAlgorithm hash, MonadRandom m)+ => OAEPParams hash ByteString ByteString+ -> BlindedKey+ -> ByteString+ -- ^ Cipher text+ -> m (Either Error ByteString, BlindedKey)+decryptBlinded oaep bk cipher+ | B.length cipher /= k = return (Left MessageSizeIncorrect, bk)+ | os2ip cipher >= private_n pk = return (Left MessageSizeIncorrect, bk)+ | k < 2 * hashLen + 2 = return (Left InvalidParameters, bk)+ | otherwise = do+ (m, bk') <- dpBlinded bk cipher+ return (unpad oaep k m, bk')+ where+ pk = blindedPrivateKey bk+ k = private_size pk+ hashLen = hashDigestSize (oaepHash oaep)
Crypto/PubKey/RSA/PKCS15.hs view
@@ -20,6 +20,11 @@ signDigestInfo, signSaferDigestInfo, + -- * Private key operations with a kept blinding+ decryptBlinded,+ signDigestBlinded,+ signDigestInfoBlinded,+ -- * Public key operations encrypt, verify,@@ -33,7 +38,7 @@ import Crypto.Hash import Crypto.Number.Serialize (os2ip) import Crypto.PubKey.Internal (and')-import Crypto.PubKey.RSA (generateBlinder)+import Crypto.PubKey.RSA.Blinded.Internal import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.Random.Types@@ -486,7 +491,8 @@ -- "convert" must be apply to "c". | otherwise = unpad $ dp blinder pk $ B.convert c --- | decrypt message using the private key and by automatically generating a blinder.+-- | decrypt message using the private key, blinded with the pair kept for+-- this key; see "Crypto.PubKey.RSA.Blinded". decryptSafer :: (MonadRandom m, ByteArray ba) => PrivateKey@@ -494,10 +500,30 @@ -> ByteString -- ^ cipher text -> m (Either Error ba)-decryptSafer pk b = do- blinder <- generateBlinder (private_n pk)- return (decrypt (Just blinder) pk b)+decryptSafer pk b+ | B.length b /= private_size pk = return (Left MessageSizeIncorrect)+ | os2ip b >= private_n pk = return (Left MessageSizeIncorrect)+ | otherwise = do+ d <- drawFor pk+ return $ withBlindingFor pk d $ \pair -> unpad (dpWithPair pair pk (B.convert b)) +-- | 'decrypt' with the blinding a t'BlindedKey' keeps, and the key for the+-- next operation.+decryptBlinded+ :: (MonadRandom m, ByteArray ba)+ => BlindedKey+ -> ByteString+ -- ^ cipher text+ -> m (Either Error ba, BlindedKey)+decryptBlinded bk c+ | B.length c /= private_size pk = return (Left MessageSizeIncorrect, bk)+ | os2ip c >= private_n pk = return (Left MessageSizeIncorrect, bk)+ | otherwise = do+ (m, bk') <- dpBlinded bk (B.convert c)+ return (unpad m, bk')+ where+ pk = blindedPrivateKey bk+ -- | encrypt a bytestring using the public key. -- -- The message needs to be smaller than the key size - 11.@@ -538,7 +564,8 @@ "Use signDigest, or signDigestInfo when the message is already a DigestInfo" #-} --- | sign message using the private key and by automatically generating a blinder.+-- | sign message using the private key, blinded with the pair kept for this+-- key; see "Crypto.PubKey.RSA.Blinded". -- -- __Deprecated.__ Use 'signSaferDigest', or 'signSaferDigestInfo'. signSafer@@ -551,8 +578,8 @@ -- ^ message to sign -> m (Either Error ByteString) signSafer hashAlg pk m = do- blinder <- generateBlinder (private_n pk)- return (sign (Just blinder) hashAlg pk m)+ d <- drawFor pk+ return $ signWithBlindingFor pk d (makeSignature hashAlg (private_size pk) m) {-# DEPRECATED signSafer "Use signSaferDigest, or signSaferDigestInfo when the message is already a DigestInfo"@@ -632,8 +659,8 @@ signDigest blinder pk digest = dp blinder pk `fmap` padSignature (private_size pk) (hashDigestASN1 digest) --- | 'signDigest' with a blinder generated for the occasion, as 'signSafer'--- is to 'sign'.+-- | 'signDigest' blinded with the pair kept for this key, as 'signSafer' is+-- to 'sign'; see "Crypto.PubKey.RSA.Blinded". signSaferDigest :: (HashAlgorithmASN1 hashAlg, MonadRandom m) => PrivateKey@@ -642,9 +669,22 @@ -- ^ digest of the message to sign -> m (Either Error ByteString) signSaferDigest pk digest = do- blinder <- generateBlinder (private_n pk)- return (signDigest (Just blinder) pk digest)+ d <- drawFor pk+ return $+ signWithBlindingFor pk d (padSignature (private_size pk) (hashDigestASN1 digest)) +-- | 'signDigest' with the blinding a t'BlindedKey' keeps, and the key for the+-- next operation.+signDigestBlinded+ :: (HashAlgorithmASN1 hashAlg, MonadRandom m)+ => BlindedKey+ -> Digest hashAlg+ -- ^ digest of the message to sign+ -> m (Either Error ByteString, BlindedKey)+signDigestBlinded bk digest =+ signBlindedEncoded bk $+ padSignature (private_size (blindedPrivateKey bk)) (hashDigestASN1 digest)+ -- | Sign something that is already a DigestInfo, the ASN.1 structure -- naming a hash algorithm and carrying a digest under it. --@@ -666,7 +706,7 @@ signDigestInfo blinder pk di = dp blinder pk `fmap` padSignature (private_size pk) di --- | 'signDigestInfo' with a blinder generated for the occasion.+-- | 'signDigestInfo' blinded with the pair kept for this key. signSaferDigestInfo :: MonadRandom m => PrivateKey@@ -675,8 +715,37 @@ -- ^ a DigestInfo, encoded -> m (Either Error ByteString) signSaferDigestInfo pk di = do- blinder <- generateBlinder (private_n pk)- return (signDigestInfo (Just blinder) pk di)+ d <- drawFor pk+ return $ signWithBlindingFor pk d (padSignature (private_size pk) di)++-- | 'signDigestInfo' with the blinding a t'BlindedKey' keeps, and the key for+-- the next operation.+signDigestInfoBlinded+ :: MonadRandom m+ => BlindedKey+ -> ByteString+ -- ^ a DigestInfo, encoded+ -> m (Either Error ByteString, BlindedKey)+signDigestInfoBlinded bk di =+ signBlindedEncoded bk $ padSignature (private_size (blindedPrivateKey bk)) di++-- | The private-key operation on an encoded signature, if there is one; the+-- key is used up only if there is.+signBlindedEncoded+ :: MonadRandom m+ => BlindedKey+ -> Either Error ByteString+ -> m (Either Error ByteString, BlindedKey)+signBlindedEncoded bk (Left err) = return (Left err, bk)+signBlindedEncoded bk (Right em) = do+ (s, bk') <- dpBlinded bk em+ return (Right s, bk')++-- | The same, with the pair the @Safer@ functions keep for this key.+signWithBlindingFor+ :: PrivateKey -> Draw -> Either Error ByteString -> Either Error ByteString+signWithBlindingFor _ _ (Left err) = Left err+signWithBlindingFor pk d (Right em) = Right (withBlindingFor pk d (\pair -> dpWithPair pair pk em)) -- | Verify a signature over a digest. The checks are 'verify's. verifyDigest
Crypto/PubKey/RSA/PSS.hs view
@@ -16,6 +16,8 @@ signDigest, signSafer, signDigestSafer,+ signBlinded,+ signDigestBlinded, verify, verifyDigest, ) where@@ -24,7 +26,7 @@ import Crypto.Number.Basic (numBits) import Crypto.Number.Serialize (os2ip) import Crypto.PubKey.MaskGenFunction-import Crypto.PubKey.RSA (generateBlinder)+import Crypto.PubKey.RSA.Blinded.Internal import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.Random.Types@@ -85,9 +87,20 @@ -> Digest hash -- ^ Message digest -> Either Error ByteString-signDigestWithSalt salt blinder params pk digest+signDigestWithSalt salt blinder params pk digest =+ dp blinder pk <$> encodeDigest salt params pk digest++-- | The encoded message the private-key operation is applied to.+encodeDigest+ :: HashAlgorithm hash+ => ByteString+ -> PSSParams hash ByteString ByteString+ -> PrivateKey+ -> Digest hash+ -> Either Error ByteString+encodeDigest salt params pk digest | emLen < hashLen + saltLen + 2 = Left InvalidParameters- | otherwise = Right $ dp blinder pk em+ | otherwise = Right em where k = private_size pk emLen = if emTruncate pubBits then k - 1 else k@@ -164,7 +177,8 @@ salt <- getRandomBytes (pssSaltLength params) return (signDigestWithSalt salt blinder params pk digest) --- | Sign using the PSS Parameters and an automatically generated blinder.+-- | Sign using the PSS Parameters, blinded with the pair kept for this key;+-- see "Crypto.PubKey.RSA.Blinded". signSafer :: (HashAlgorithm hash, MonadRandom m) => PSSParams hash ByteString ByteString@@ -174,11 +188,10 @@ -> ByteString -- ^ message to sign -> m (Either Error ByteString)-signSafer params pk m = do- blinder <- generateBlinder (private_n pk)- sign (Just blinder) params pk m+signSafer params pk m = signDigestSafer params pk (hashWith (pssHash params) m) --- | Sign using the PSS Parameters and an automatically generated blinder.+-- | Sign using the PSS Parameters, blinded with the pair kept for this key;+-- see "Crypto.PubKey.RSA.Blinded". signDigestSafer :: (HashAlgorithm hash, MonadRandom m) => PSSParams hash ByteString ByteString@@ -189,8 +202,39 @@ -- ^ message digst -> m (Either Error ByteString) signDigestSafer params pk digest = do- blinder <- generateBlinder (private_n pk)- signDigest (Just blinder) params pk digest+ salt <- getRandomBytes (pssSaltLength params)+ d <- drawFor pk+ return $ case encodeDigest salt params pk digest of+ Left err -> Left err+ Right em -> Right (withBlindingFor pk d (\pair -> dpWithPair pair pk em))++-- | 'signSafer' with the blinding a t'BlindedKey' keeps, and the key for the+-- next operation.+signBlinded+ :: (HashAlgorithm hash, MonadRandom m)+ => PSSParams hash ByteString ByteString+ -> BlindedKey+ -> ByteString+ -- ^ message to sign+ -> m (Either Error ByteString, BlindedKey)+signBlinded params bk m = signDigestBlinded params bk (hashWith (pssHash params) m)++-- | 'signDigestSafer' with the blinding a t'BlindedKey' keeps, and the key+-- for the next operation.+signDigestBlinded+ :: (HashAlgorithm hash, MonadRandom m)+ => PSSParams hash ByteString ByteString+ -> BlindedKey+ -> Digest hash+ -- ^ message digest+ -> m (Either Error ByteString, BlindedKey)+signDigestBlinded params bk digest = do+ salt <- getRandomBytes (pssSaltLength params)+ case encodeDigest salt params (blindedPrivateKey bk) digest of+ Left err -> return (Left err, bk)+ Right em -> do+ (s, bk') <- dpBlinded bk em+ return (Right s, bk') -- | Verify a signature using the PSS Parameters verify
Crypto/PubKey/RSA/Prim.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE BangPatterns #-}+ -- | -- Module : Crypto.PubKey.RSA.Prim -- License : BSD-style@@ -12,9 +14,18 @@ ep, ) where +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 Crypto.Internal.ByteArray (ByteArray)+import Crypto.Internal.Compat (unsafeDoIO)+import Crypto.Number.Basic (numBytes) import Crypto.Number.ModArithmetic (expFast, expSafe) import Crypto.Number.Serialize (i2ospOf_, os2ip)+import qualified Crypto.Number.Serialize.Internal as Internal import Crypto.PubKey.RSA.Types {- dpSlow computes the decrypted message not using any precomputed cache value.@@ -33,17 +44,62 @@ where re = expFast r (public_e $ private_pub pk) (private_n pk) iC = multiplication re (os2ip c) (private_n pk)- m1 = expSafe iC (private_dP pk) (private_p pk)- m2 = expSafe iC (private_dQ pk) (private_q pk)+ (m1, m2) = crtHalves iC pk 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)) where iC = os2ip c- m1 = expSafe iC (private_dP pk) (private_p pk)- m2 = expSafe iC (private_dQ pk) (private_q pk)+ (m1, m2) = crtHalves iC pk h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p 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.+crtHalves :: Integer -> PrivateKey -> (Integer, Integer)+crtHalves c pk = case expSafeX2 (c `mod` p) dP p (c `mod` q) dQ q of+ Just r -> r+ Nothing -> (expSafe c dP p, expSafe c dQ q)+ where+ p = private_p pk+ q = private_q pk+ dP = private_dP pk+ dQ = private_dQ pk++-- | Two secure exponentiations in one call. The bases are reduced already+-- and the moduli are the same length; both exponents go in at that length,+-- so the length the C sees is the modulus', as 'expSafe' pads to whole words.+expSafeX2 :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Maybe (Integer, Integer)+expSafeX2 b1 e1 m1 b2 e2 m2+ | numBytes m2 /= len || not (odd m1 && odd m2) = Nothing+ | e1 < 0 || e2 < 0 || numBytes e1 > len || numBytes e2 > len = Nothing+ | otherwise = unsafeDoIO $+ allocaBytes (8 * len) $ \start -> case take 8 (iterate (`plusPtr` len) start) of+ [o1, pb1, pe1, pm1, o2, pb2, pe2, pm2] -> do+ mapM_+ (\(v, ptr) -> Internal.i2ospOf v ptr len)+ [(b1, pb1), (e1, pe1), (m1, pm1), (b2, pb2), (e2, pe2), (m2, pm2)]+ r <- c_powm_sec_x2 o1 pb1 l pe1 l pm1 l o2 pb2 l pe2 l pm2 l+ -- the exponents are the caller's secrets+ memSet pe1 0 len+ memSet pe2 0 len+ if r /= 0+ then return Nothing+ else do+ !v1 <- Internal.os2ip o1 len+ !v2 <- Internal.os2ip o2 len+ return (Just (v1, v2))+ _ -> return Nothing+ where+ !len = numBytes m1+ l = fromIntegral len :: Word32++foreign import ccall safe "crypton_powm_sec_x2"+ c_powm_sec_x2+ :: Ptr Word8 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32+ -> Ptr Word8 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32+ -> IO CInt -- | Compute the RSA decrypt primitive. -- if the p and q numbers are available, then dpFast is used
Crypto/System/CPU.hs view
@@ -26,6 +26,7 @@ ADX, VAES, VAES512,+ AVX512IFMA, -- AArch64 NEON, ARMAES,@@ -112,6 +113,11 @@ pattern VAES512 :: ProcessorOption pattern VAES512 = ProcessorOption 10 +-- | The AVX-512 52-bit integer multiply-adds, with AVX-512 F and VL, and the+-- operating system saving their state: RSA's private-key operation uses them.+pattern AVX512IFMA :: ProcessorOption+pattern AVX512IFMA = ProcessorOption 19+ -- | Advanced SIMD, which is not optional on AArch64. pattern NEON :: ProcessorOption pattern NEON = ProcessorOption 11@@ -161,6 +167,7 @@ show ADX = "ADX" show VAES = "VAES" show VAES512 = "VAES512"+ show AVX512IFMA = "AVX512IFMA" show NEON = "NEON" show ARMAES = "ARMAES" show ARMPMULL = "ARMPMULL"@@ -193,7 +200,7 @@ -- 2 is not asked for and has no name: it was RDRAND, which crypton no -- longer dispatches on. The number is left out rather than reused, so -- that the others keep the values they had.- allOptions = [ProcessorOption n | n <- [0 .. 18], n /= 2]+ allOptions = [ProcessorOption n | n <- [0 .. 19], n /= 2] askC (ProcessorOption n) = (/= 0) <$> crypton_cpu_option (fromIntegral n) {-# NOINLINE processorOptions #-}
cbits/crypton_bitfn.h view
@@ -127,23 +127,6 @@ } #endif -#ifndef ARCH_HAS_MEMORY_ZERO-static inline void memory_zero(void *ptr, uint32_t len)-{- uint32_t *ptr32 = ptr;- uint8_t *ptr8;- int i;-- for (i = 0; i < len / 4; i++)- *ptr32++ = 0;- if (len % 4) {- ptr8 = (uint8_t *) ptr32;- for (i = len % 4; i >= 0; i--)- ptr8[i] = 0;- }-}-#endif- #ifndef ARCH_HAS_ARRAY_COPY32 static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb) {
cbits/crypton_chacha.c view
@@ -109,8 +109,9 @@ #define ALIGNED64(PTR) \ (((uintptr_t)(const void *)(PTR)) % 8 == 0) -static const uint8_t sigma[16] = "expand 32-byte k";-static const uint8_t tau[16] = "expand 16-byte k";+/* sixteen bytes are read; the seventeenth is the string's terminator */+static const uint8_t sigma[17] = "expand 32-byte k";+static const uint8_t tau[17] = "expand 16-byte k"; static void chacha_core(int rounds, crypton_chacha_block *out, const crypton_chacha_state *in) {@@ -384,7 +385,7 @@ } /* xor as much as needed */- for (i = 0; i < bytes; i++)+ for (i = 0; i < (int) bytes; i++) dst[i] = src[i] ^ out.b[i]; /* copy the left over in the buffer */@@ -510,7 +511,7 @@ } /* xor as much as needed */- for (i = 0; i < bytes; i++)+ for (i = 0; i < (int) bytes; i++) dst[i] = out.b[i]; /* copy the left over in the buffer */
cbits/crypton_cpu.c view
@@ -512,6 +512,14 @@ * AVX-512 at all and never reaches here. */ && !(amd && family == 0x19)) f |= CRYPTON_X86_VAES512;+ /* IFMA (bit 21) with F (16) and VL (31), and the same+ * AVX-512 state. Zen 4 is not left out here: RSA's+ * multiplication uses the 256-bit form. */+ if ((f & CRYPTON_X86_AVX2)+ && (ebx & (1 << 16)) && (ebx & (1 << 21))+ && (ebx & (1u << 31))+ && ((xcr0() & 0xe6) == 0xe6))+ f |= CRYPTON_X86_IFMA; } #ifdef CRYPTON_CPU_TESTING_ADX f |= CRYPTON_X86_ADX;@@ -602,6 +610,7 @@ #define OPT_ARMSHA512 16 #define OPT_PPCAES 17 #define OPT_PPCVPMSUM 18+#define OPT_IFMA 19 int crypton_cpu_option(unsigned int option) {@@ -619,6 +628,7 @@ case OPT_ADX: return (f & CRYPTON_X86_ADX) != 0; case OPT_VAES: return (f & CRYPTON_X86_VAES) != 0; case OPT_VAES512: return (f & CRYPTON_X86_VAES512) != 0;+ case OPT_IFMA: return (f & CRYPTON_X86_IFMA) != 0; default: return 0; } #else
cbits/crypton_cpu.h view
@@ -65,6 +65,9 @@ * bits of XCR0 than AVX2 wants: the mask registers and the two upper halves * of the vector registers. */ #define CRYPTON_X86_VAES512 256+/* AVX-512 IFMA, the 52-bit multiply-adds, with F and VL for the 256-bit form+ * RSA uses them in: EVEX-encoded, so they want the AVX-512 state saved too. */+#define CRYPTON_X86_IFMA 512 #ifdef ARCH_X86 uint32_t crypton_x86_simd_features(void); #endif
+ cbits/crypton_mont.h view
@@ -0,0 +1,9015 @@+/* 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);+}++#endif
+ cbits/crypton_mont.py view
@@ -0,0 +1,168 @@+#!/usr/bin/env python3+"""Generate cbits/crypton_mont.h: Montgomery multiplication and squaring for+AArch64 at the limb counts of RSA's CRT halves, fully unrolled and+product-scanning.++Usage: python3 cbits/crypton_mont.py > cbits/crypton_mont.h++The result is a column at a time, with the reduction folded into the same+scan (the FIPS method), so the running sum stays in registers instead of+going through memory a row at a time. A column's products are spread over+three accumulators and added together at its end, since one accumulator's+carry chain is what holds the core back, not its multipliers. In a square,+each product off the diagonal is summed once, doubled, and added in.+"""++SIZES = (16, 24, 32)++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. */+#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)+"""++FOOTER = """\+#endif+"""+++class Column:+ """Products added to accumulators, each set up by its first product."""++ def __init__(self, w):+ self.w = w+ self.started = set()++ def add(self, acc, x, y):+ if acc == "t" or acc in self.started:+ self.w(f"\tMONT_MAC({acc}0, {acc}1, {acc}2, {x}, {y});")+ else:+ self.w(f"\tMONT_MUL({acc}0, {acc}1, {acc}2, {x}, {y});")+ self.started.add(acc)++ def fold(self, into, acc):+ if acc in self.started:+ self.w(f"\tMONT_ADD({into}0, {into}1, {into}2, {acc}0, {acc}1, {acc}2);")+++def column(w, singles, cross):+ """singles are added once, cross twice: s and c take the cross products,+ t, v and w take the rest, and all of them end up in t."""+ col = Column(w)+ for k, (x, y) in enumerate(cross):+ col.add("s" if k % 2 == 0 else "c", x, y)+ for k, (x, y) in enumerate(singles):+ col.add("tvw"[k % 3], x, y)+ col.fold("t", "v")+ col.fold("t", "w")+ if cross:+ col.fold("s", "c")+ w("\tMONT_DBL(s0, s1, s2);")+ w("\tMONT_ADD(t0, t1, t2, s0, s1, s2);")+++def gen(n, square):+ out = []+ w = out.append+ name = f"crypton_mont_{'sqr' if square else 'mul'}{n}"+ args = "const limb_t *a," if square else "const limb_t *a, const limb_t *b,"+ if square:+ w(f"/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */")+ else:+ w(f"/* r = a * b * R^-1 mod m, for a and b under m; t is 2n limbs of scratch */")+ w(f"static void {name}(limb_t *r, {args}")+ w(f"{' ' * len(f'static void {name}(')}const limb_t *m, limb_t n0, limb_t *t)")+ w("{")+ w(f"\tlimb_t *u = t, *z = t + {n};")+ w("\tlimb_t t0 = 0, t1 = 0, t2 = 0, v0, v1, v2, w0, w1, w2, borrow, take;")+ if square:+ w("\tlimb_t s0, s1, s2, c0, c1, c2;")+ w("")+ for i in range(2 * n - 1):+ w(f"\t/* column {i} */")+ singles, cross = [], []+ for j in range(max(0, i - n + 1), min(i, n - 1) + 1):+ k = i - j+ if not square:+ singles.append((f"a[{j}]", f"b[{k}]"))+ elif j < k:+ cross.append((f"a[{j}]", f"a[{k}]"))+ elif j == k:+ singles.append((f"a[{j}]", f"a[{j}]"))+ for j in range(max(0, i - n + 1), min(i, n)):+ singles.append((f"u[{j}]", f"m[{i - j}]"))+ column(w, singles, cross)+ if i < n:+ w(f"\tu[{i}] = t0 * n0;")+ w(f"\tMONT_MAC(t0, t1, t2, u[{i}], m[0]);")+ else:+ w(f"\tz[{i - n}] = t0;")+ w("\tt0 = t1;")+ w("\tt1 = t2;")+ w("\tt2 = 0;")+ w(f"\tz[{n - 1}] = t0;")+ w("")+ w("\t/* under 2m, with t1 the bit above n limbs: at most one subtraction */")+ w(f"\tborrow = sub_n(r, z, m, {n});")+ w("\ttake = t1 | (borrow ^ 1);")+ w(f"\tselect_n(r, r, z, take & 1, {n});")+ w("}")+ w("")+ return "\n".join(out)+++def main():+ print(HEADER)+ for n in SIZES:+ print(gen(n, False))+ print(gen(n, True))+ print(FOOTER, end="")+++if __name__ == "__main__":+ main()
− cbits/crypton_mont_sqr.h
@@ -1,3751 +0,0 @@-/* Generated by cbits/crypton_mont_sqr.py; do not edit.- *- * Montgomery squaring for AArch64 at 16, 24 and 32 limbs, the halves of- * RSA-2048, -3072 and -4096. Each answers what mont_sqr answers. */-#ifndef CRYPTON_MONT_SQR_H-#define CRYPTON_MONT_SQR_H--#include "crypton_bignum.h"--/* (t2:t1:t0) += x * y */-#define MONT_SQR_MAC(t0, t1, t2, x, y) \- do { \- limb_t lo_, hi_; \- __asm__("mul\t%0, %5, %6\n\t" \- "umulh\t%1, %5, %6\n\t" \- "adds\t%2, %2, %0\n\t" \- "adcs\t%3, %3, %1\n\t" \- "adc\t%4, %4, xzr" \- : "=&r"(lo_), "=&r"(hi_), "+r"(t0), "+r"(t1), "+r"(t2) \- : "r"(x), "r"(y) \- : "cc"); \- } while (0)--/* (s2:s1:s0) = x * y */-#define MONT_SQR_MUL(s0, s1, s2, x, y) \- __asm__("mul\t%0, %3, %4\n\t" \- "umulh\t%1, %3, %4\n\t" \- "mov\t%2, xzr" \- : "=&r"(s0), "=&r"(s1), "=r"(s2) \- : "r"(x), "r"(y))--/* (t2:t1:t0) += 2 * (s2:s1:s0) */-#define MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2) \- do { \- s2 = (s2 << 1) | (s1 >> 63); \- s1 = (s1 << 1) | (s0 >> 63); \- s0 <<= 1; \- __asm__("adds\t%0, %0, %3\n\t" \- "adcs\t%1, %1, %4\n\t" \- "adc\t%2, %2, %5" \- : "+r"(t0), "+r"(t1), "+r"(t2) \- : "r"(s0), "r"(s1), "r"(s2) \- : "cc"); \- } while (0)--/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */-static void crypton_mont_sqr16(limb_t *r, const limb_t *a, const limb_t *m,- limb_t n0, limb_t *t)-{- limb_t *u = t, *z = t + 16;- limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;-- /* column 0 */- MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);- u[0] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 1 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);- u[1] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 2 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);- u[2] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 3 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);- u[3] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 4 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);- u[4] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 5 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);- u[5] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 6 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);- u[6] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 7 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);- u[7] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 8 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);- u[8] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 9 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);- u[9] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 10 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);- u[10] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 11 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);- u[11] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 12 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);- u[12] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 13 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);- u[13] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 14 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);- u[14] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 15 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);- u[15] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 16 */- MONT_SQR_MUL(s0, s1, s2, a[1], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);- z[0] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 17 */- MONT_SQR_MUL(s0, s1, s2, a[2], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);- z[1] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 18 */- MONT_SQR_MUL(s0, s1, s2, a[3], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);- z[2] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 19 */- MONT_SQR_MUL(s0, s1, s2, a[4], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);- z[3] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 20 */- MONT_SQR_MUL(s0, s1, s2, a[5], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);- z[4] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 21 */- MONT_SQR_MUL(s0, s1, s2, a[6], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);- z[5] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 22 */- MONT_SQR_MUL(s0, s1, s2, a[7], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);- z[6] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 23 */- MONT_SQR_MUL(s0, s1, s2, a[8], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);- z[7] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 24 */- MONT_SQR_MUL(s0, s1, s2, a[9], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);- z[8] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 25 */- MONT_SQR_MUL(s0, s1, s2, a[10], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);- z[9] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 26 */- MONT_SQR_MUL(s0, s1, s2, a[11], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);- z[10] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 27 */- MONT_SQR_MUL(s0, s1, s2, a[12], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);- z[11] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 28 */- MONT_SQR_MUL(s0, s1, s2, a[13], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);- z[12] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 29 */- MONT_SQR_MUL(s0, s1, s2, a[14], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);- z[13] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 30 */- MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);- z[14] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- z[15] = t0;-- /* under 2m, with t1 the bit above n limbs: at most one subtraction */- borrow = sub_n(r, z, m, 16);- take = t1 | (borrow ^ 1);- select_n(r, r, z, take & 1, 16);-}--/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */-static void crypton_mont_sqr24(limb_t *r, const limb_t *a, const limb_t *m,- limb_t n0, limb_t *t)-{- limb_t *u = t, *z = t + 24;- limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;-- /* column 0 */- MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);- u[0] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 1 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);- u[1] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 2 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);- u[2] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 3 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);- u[3] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 4 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);- u[4] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 5 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);- u[5] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 6 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);- u[6] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 7 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);- u[7] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 8 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);- u[8] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 9 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);- u[9] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 10 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);- u[10] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 11 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);- u[11] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 12 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);- u[12] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 13 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);- u[13] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 14 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);- u[14] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 15 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);- u[15] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 16 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);- u[16] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[16], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 17 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[1]);- u[17] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[17], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 18 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[1]);- u[18] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[18], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 19 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[1]);- u[19] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[19], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 20 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[1]);- u[20] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[20], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 21 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[1]);- u[21] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[21], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 22 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[1]);- u[22] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[22], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 23 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[1]);- u[23] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[23], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 24 */- MONT_SQR_MUL(s0, s1, s2, a[1], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[1]);- z[0] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 25 */- MONT_SQR_MUL(s0, s1, s2, a[2], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[2], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[2]);- z[1] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 26 */- MONT_SQR_MUL(s0, s1, s2, a[3], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[3]);- z[2] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 27 */- MONT_SQR_MUL(s0, s1, s2, a[4], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[4], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[4]);- z[3] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 28 */- MONT_SQR_MUL(s0, s1, s2, a[5], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[5]);- z[4] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 29 */- MONT_SQR_MUL(s0, s1, s2, a[6], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[6], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[6]);- z[5] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 30 */- MONT_SQR_MUL(s0, s1, s2, a[7], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[16]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[7]);- z[6] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 31 */- MONT_SQR_MUL(s0, s1, s2, a[8], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[16]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[8], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[8]);- z[7] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 32 */- MONT_SQR_MUL(s0, s1, s2, a[9], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[17]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[16], a[16]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[9]);- z[8] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 33 */- MONT_SQR_MUL(s0, s1, s2, a[10], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[17]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[10], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[10]);- z[9] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 34 */- MONT_SQR_MUL(s0, s1, s2, a[11], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[18]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[17], a[17]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[11]);- z[10] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 35 */- MONT_SQR_MUL(s0, s1, s2, a[12], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[18]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[12], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[12]);- z[11] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 36 */- MONT_SQR_MUL(s0, s1, s2, a[13], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[19]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[18], a[18]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[13]);- z[12] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 37 */- MONT_SQR_MUL(s0, s1, s2, a[14], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[19]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[14], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[14]);- z[13] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 38 */- MONT_SQR_MUL(s0, s1, s2, a[15], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[20]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[19], a[19]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[15]);- z[14] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 39 */- MONT_SQR_MUL(s0, s1, s2, a[16], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[20]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[16], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[16]);- z[15] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 40 */- MONT_SQR_MUL(s0, s1, s2, a[17], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[21]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[20], a[20]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[17]);- z[16] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 41 */- MONT_SQR_MUL(s0, s1, s2, a[18], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[21]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[18], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[18]);- z[17] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 42 */- MONT_SQR_MUL(s0, s1, s2, a[19], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[22]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[21], a[21]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[19]);- z[18] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 43 */- MONT_SQR_MUL(s0, s1, s2, a[20], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[22]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[20], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[20]);- z[19] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 44 */- MONT_SQR_MUL(s0, s1, s2, a[21], a[23]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[22], a[22]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[21]);- z[20] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 45 */- MONT_SQR_MUL(s0, s1, s2, a[22], a[23]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[22], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[22]);- z[21] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 46 */- MONT_SQR_MAC(t0, t1, t2, a[23], a[23]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[23]);- z[22] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- z[23] = t0;-- /* under 2m, with t1 the bit above n limbs: at most one subtraction */- borrow = sub_n(r, z, m, 24);- take = t1 | (borrow ^ 1);- select_n(r, r, z, take & 1, 24);-}--/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */-static void crypton_mont_sqr32(limb_t *r, const limb_t *a, const limb_t *m,- limb_t n0, limb_t *t)-{- limb_t *u = t, *z = t + 32;- limb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;-- /* column 0 */- MONT_SQR_MAC(t0, t1, t2, a[0], a[0]);- u[0] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[0], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 1 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[1]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[1]);- u[1] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[1], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 2 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[1], a[1]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[1]);- u[2] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[2], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 3 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[3]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[2]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[1]);- u[3] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[3], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 4 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[2], a[2]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[1]);- u[4] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[4], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 5 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[4]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[3]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[1]);- u[5] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[5], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 6 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[3], a[3]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[1]);- u[6] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[6], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 7 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[5]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[4]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[1]);- u[7] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[7], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 8 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[4], a[4]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[1]);- u[8] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[8], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 9 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[6]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[5]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[1]);- u[9] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[9], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 10 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[5], a[5]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[1]);- u[10] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[10], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 11 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[7]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[6]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[1]);- u[11] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[11], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 12 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[6], a[6]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[1]);- u[12] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[12], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 13 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[8]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[7]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[1]);- u[13] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[13], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 14 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[7], a[7]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[1]);- u[14] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[14], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 15 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[9]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[8]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[1]);- u[15] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[15], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 16 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[8], a[8]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[1]);- u[16] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[16], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 17 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[10]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[9]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[1]);- u[17] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[17], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 18 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[9], a[9]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[1]);- u[18] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[18], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 19 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[11]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[10]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[1]);- u[19] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[19], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 20 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[10], a[10]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[1]);- u[20] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[20], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 21 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[12]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[11]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[1]);- u[21] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[21], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 22 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[11], a[11]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[1]);- u[22] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[22], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 23 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[13]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[12]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[1]);- u[23] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[23], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 24 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[12], a[12]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[1]);- u[24] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[24], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 25 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[14]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[13]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[1]);- u[25] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[25], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 26 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[13], a[13]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[1]);- u[26] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[26], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 27 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[15]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[14]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[1]);- u[27] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[27], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 28 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[14], a[14]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[1]);- u[28] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[28], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 29 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[16]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[15]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[1]);- u[29] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[29], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 30 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[16]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[15], a[15]);- MONT_SQR_MAC(t0, t1, t2, u[0], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[1]);- u[30] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[30], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 31 */- MONT_SQR_MUL(s0, s1, s2, a[0], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[1], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[17]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[16]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[0], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[1]);- u[31] = t0 * n0;- MONT_SQR_MAC(t0, t1, t2, u[31], m[0]);- t0 = t1;- t1 = t2;- t2 = 0;- /* column 32 */- MONT_SQR_MUL(s0, s1, s2, a[1], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[2], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[17]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[16], a[16]);- MONT_SQR_MAC(t0, t1, t2, u[1], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[2], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[2]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[1]);- z[0] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 33 */- MONT_SQR_MUL(s0, s1, s2, a[2], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[3], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[18]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[17]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[2], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[3]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[2]);- z[1] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 34 */- MONT_SQR_MUL(s0, s1, s2, a[3], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[4], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[18]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[17], a[17]);- MONT_SQR_MAC(t0, t1, t2, u[3], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[4], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[4]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[3]);- z[2] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 35 */- MONT_SQR_MUL(s0, s1, s2, a[4], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[5], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[19]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[18]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[4], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[5]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[4]);- z[3] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 36 */- MONT_SQR_MUL(s0, s1, s2, a[5], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[6], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[19]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[18], a[18]);- MONT_SQR_MAC(t0, t1, t2, u[5], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[6], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[6]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[5]);- z[4] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 37 */- MONT_SQR_MUL(s0, s1, s2, a[6], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[7], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[20]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[19]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[6], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[7]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[6]);- z[5] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 38 */- MONT_SQR_MUL(s0, s1, s2, a[7], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[8], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[20]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[19], a[19]);- MONT_SQR_MAC(t0, t1, t2, u[7], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[8], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[8]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[7]);- z[6] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 39 */- MONT_SQR_MUL(s0, s1, s2, a[8], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[9], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[21]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[20]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[8], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[9]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[8]);- z[7] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 40 */- MONT_SQR_MUL(s0, s1, s2, a[9], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[10], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[21]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[20], a[20]);- MONT_SQR_MAC(t0, t1, t2, u[9], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[10], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[10]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[9]);- z[8] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 41 */- MONT_SQR_MUL(s0, s1, s2, a[10], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[11], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[22]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[21]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[10], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[11]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[10]);- z[9] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 42 */- MONT_SQR_MUL(s0, s1, s2, a[11], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[12], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[22]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[21], a[21]);- MONT_SQR_MAC(t0, t1, t2, u[11], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[12], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[12]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[11]);- z[10] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 43 */- MONT_SQR_MUL(s0, s1, s2, a[12], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[13], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[23]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[22]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[12], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[13]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[12]);- z[11] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 44 */- MONT_SQR_MUL(s0, s1, s2, a[13], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[14], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[23]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[22], a[22]);- MONT_SQR_MAC(t0, t1, t2, u[13], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[14], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[14]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[13]);- z[12] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 45 */- MONT_SQR_MUL(s0, s1, s2, a[14], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[15], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[24]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[23]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[14], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[15]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[14]);- z[13] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 46 */- MONT_SQR_MUL(s0, s1, s2, a[15], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[16], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[24]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[23], a[23]);- MONT_SQR_MAC(t0, t1, t2, u[15], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[16], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[16]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[15]);- z[14] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 47 */- MONT_SQR_MUL(s0, s1, s2, a[16], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[17], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[25]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[24]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[16], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[17]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[16]);- z[15] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 48 */- MONT_SQR_MUL(s0, s1, s2, a[17], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[18], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[25]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[24], a[24]);- MONT_SQR_MAC(t0, t1, t2, u[17], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[18], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[18]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[17]);- z[16] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 49 */- MONT_SQR_MUL(s0, s1, s2, a[18], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[19], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[26]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[25]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[18], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[19]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[18]);- z[17] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 50 */- MONT_SQR_MUL(s0, s1, s2, a[19], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[20], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[26]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[25], a[25]);- MONT_SQR_MAC(t0, t1, t2, u[19], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[20], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[20]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[19]);- z[18] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 51 */- MONT_SQR_MUL(s0, s1, s2, a[20], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[21], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[27]);- MONT_SQR_MAC(s0, s1, s2, a[25], a[26]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[20], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[21]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[20]);- z[19] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 52 */- MONT_SQR_MUL(s0, s1, s2, a[21], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[22], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[25], a[27]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[26], a[26]);- MONT_SQR_MAC(t0, t1, t2, u[21], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[22], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[22]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[21]);- z[20] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 53 */- MONT_SQR_MUL(s0, s1, s2, a[22], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[23], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[25], a[28]);- MONT_SQR_MAC(s0, s1, s2, a[26], a[27]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[22], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[23]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[22]);- z[21] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 54 */- MONT_SQR_MUL(s0, s1, s2, a[23], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[24], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[25], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[26], a[28]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[27], a[27]);- MONT_SQR_MAC(t0, t1, t2, u[23], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[24], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[24]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[23]);- z[22] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 55 */- MONT_SQR_MUL(s0, s1, s2, a[24], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[25], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[26], a[29]);- MONT_SQR_MAC(s0, s1, s2, a[27], a[28]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[24], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[25]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[24]);- z[23] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 56 */- MONT_SQR_MUL(s0, s1, s2, a[25], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[26], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[27], a[29]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[28], a[28]);- MONT_SQR_MAC(t0, t1, t2, u[25], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[26], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[26]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[25]);- z[24] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 57 */- MONT_SQR_MUL(s0, s1, s2, a[26], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[27], a[30]);- MONT_SQR_MAC(s0, s1, s2, a[28], a[29]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[26], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[27]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[26]);- z[25] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 58 */- MONT_SQR_MUL(s0, s1, s2, a[27], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[28], a[30]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[29], a[29]);- MONT_SQR_MAC(t0, t1, t2, u[27], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[28], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[28]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[27]);- z[26] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 59 */- MONT_SQR_MUL(s0, s1, s2, a[28], a[31]);- MONT_SQR_MAC(s0, s1, s2, a[29], a[30]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[28], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[29]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[28]);- z[27] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 60 */- MONT_SQR_MUL(s0, s1, s2, a[29], a[31]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, a[30], a[30]);- MONT_SQR_MAC(t0, t1, t2, u[29], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[30], m[30]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[29]);- z[28] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 61 */- MONT_SQR_MUL(s0, s1, s2, a[30], a[31]);- MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);- MONT_SQR_MAC(t0, t1, t2, u[30], m[31]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[30]);- z[29] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- /* column 62 */- MONT_SQR_MAC(t0, t1, t2, a[31], a[31]);- MONT_SQR_MAC(t0, t1, t2, u[31], m[31]);- z[30] = t0;- t0 = t1;- t1 = t2;- t2 = 0;- z[31] = t0;-- /* under 2m, with t1 the bit above n limbs: at most one subtraction */- borrow = sub_n(r, z, m, 32);- take = t1 | (borrow ^ 1);- select_n(r, r, z, take & 1, 32);-}--#endif
− cbits/crypton_mont_sqr.py
@@ -1,117 +0,0 @@-#!/usr/bin/env python3-"""Generate cbits/crypton_mont_sqr.h: Montgomery squaring for AArch64 at the-limb counts of RSA's CRT halves, fully unrolled and product-scanning.--Usage: python3 cbits/crypton_mont_sqr.py > cbits/crypton_mont_sqr.h--The result is a column at a time, with the reduction folded into the same-scan (the FIPS method), so the running sum stays in three registers instead-of going through memory a row at a time. Each product off the diagonal is-summed once into a column of its own, doubled, and added in.-"""--SIZES = (16, 24, 32)--HEADER = """\-/* Generated by cbits/crypton_mont_sqr.py; do not edit.- *- * Montgomery squaring for AArch64 at 16, 24 and 32 limbs, the halves of- * RSA-2048, -3072 and -4096. Each answers what mont_sqr answers. */-#ifndef CRYPTON_MONT_SQR_H-#define CRYPTON_MONT_SQR_H--#include "crypton_bignum.h"--/* (t2:t1:t0) += x * y */-#define MONT_SQR_MAC(t0, t1, t2, x, y) \\- do { \\- limb_t lo_, hi_; \\- __asm__("mul\\t%0, %5, %6\\n\\t" \\- "umulh\\t%1, %5, %6\\n\\t" \\- "adds\\t%2, %2, %0\\n\\t" \\- "adcs\\t%3, %3, %1\\n\\t" \\- "adc\\t%4, %4, xzr" \\- : "=&r"(lo_), "=&r"(hi_), "+r"(t0), "+r"(t1), "+r"(t2) \\- : "r"(x), "r"(y) \\- : "cc"); \\- } while (0)--/* (s2:s1:s0) = x * y */-#define MONT_SQR_MUL(s0, s1, s2, x, y) \\- __asm__("mul\\t%0, %3, %4\\n\\t" \\- "umulh\\t%1, %3, %4\\n\\t" \\- "mov\\t%2, xzr" \\- : "=&r"(s0), "=&r"(s1), "=r"(s2) \\- : "r"(x), "r"(y))--/* (t2:t1:t0) += 2 * (s2:s1:s0) */-#define MONT_SQR_ADD2(t0, t1, t2, s0, s1, s2) \\- do { \\- s2 = (s2 << 1) | (s1 >> 63); \\- s1 = (s1 << 1) | (s0 >> 63); \\- s0 <<= 1; \\- __asm__("adds\\t%0, %0, %3\\n\\t" \\- "adcs\\t%1, %1, %4\\n\\t" \\- "adc\\t%2, %2, %5" \\- : "+r"(t0), "+r"(t1), "+r"(t2) \\- : "r"(s0), "r"(s1), "r"(s2) \\- : "cc"); \\- } while (0)-"""--FOOTER = """\-#endif-"""---def gen(n):- out = []- w = out.append- w(f"/* r = a * a * R^-1 mod m, for a under m; t is 2n limbs of scratch */")- w(f"static void crypton_mont_sqr{n}(limb_t *r, const limb_t *a, const limb_t *m,")- w(f"{' ' * len(f'static void crypton_mont_sqr{n}(')}limb_t n0, limb_t *t)")- w("{")- w(f"\tlimb_t *u = t, *z = t + {n};")- w("\tlimb_t t0 = 0, t1 = 0, t2 = 0, s0, s1, s2, borrow, take;")- w("")- for i in range(2 * n - 1):- w(f"\t/* column {i} */")- pairs = [(j, i - j) for j in range(max(0, i - n + 1), n) if j < i - j]- if pairs:- j, k = pairs[0]- w(f"\tMONT_SQR_MUL(s0, s1, s2, a[{j}], a[{k}]);")- for (j, k) in pairs[1:]:- w(f"\tMONT_SQR_MAC(s0, s1, s2, a[{j}], a[{k}]);")- w("\tMONT_SQR_ADD2(t0, t1, t2, s0, s1, s2);")- if i % 2 == 0:- w(f"\tMONT_SQR_MAC(t0, t1, t2, a[{i // 2}], a[{i // 2}]);")- for j in range(max(0, i - n + 1), min(i, n)):- w(f"\tMONT_SQR_MAC(t0, t1, t2, u[{j}], m[{i - j}]);")- if i < n:- w(f"\tu[{i}] = t0 * n0;")- w(f"\tMONT_SQR_MAC(t0, t1, t2, u[{i}], m[0]);")- else:- w(f"\tz[{i - n}] = t0;")- w("\tt0 = t1;")- w("\tt1 = t2;")- w("\tt2 = 0;")- w(f"\tz[{n - 1}] = t0;")- w("")- w("\t/* under 2m, with t1 the bit above n limbs: at most one subtraction */")- w(f"\tborrow = sub_n(r, z, m, {n});")- w("\ttake = t1 | (borrow ^ 1);")- w(f"\tselect_n(r, r, z, take & 1, {n});")- w("}")- w("")- return "\n".join(out)---def main():- print(HEADER)- for n in SIZES:- print(gen(n))- print(FOOTER, end="")---if __name__ == "__main__":- main()
cbits/crypton_powm.c view
@@ -22,13 +22,14 @@ #include <crypton_powm.h> #include <crypton_bzero.h> -/* On AArch64, squaring at the RSA half sizes goes through generated code- * that scans a column at a time with the reduction folded in; see- * cbits/crypton_mont_sqr.py. CRYPTON_NO_MONT_SQR keeps mont_sqr, to compare. */-#if defined(__aarch64__) && LIMB_BITS == 64 && !defined(CRYPTON_NO_MONT_SQR) \+/* On AArch64, multiplication and squaring at the RSA half sizes go through+ * generated code that scans a column at a time with the reduction folded in;+ * see cbits/crypton_mont.py. CRYPTON_NO_MONT_FIXED keeps mont_mul and+ * mont_sqr, to compare. */+#if defined(__aarch64__) && LIMB_BITS == 64 && !defined(CRYPTON_NO_MONT_FIXED) \ && (defined(__GNUC__) || defined(__clang__))-#define CRYPTON_MONT_SQR 1-#include <crypton_mont_sqr.h>+#define CRYPTON_MONT_FIXED 1+#include <crypton_mont.h> #endif /*@@ -175,6 +176,13 @@ (void)scratch; (void)s2n; #endif+#ifdef CRYPTON_MONT_FIXED+ switch (n) {+ case 16: crypton_mont_mul16(r, a, b, m, n0, t); return;+ case 24: crypton_mont_mul24(r, a, b, m, n0, t); return;+ case 32: crypton_mont_mul32(r, a, b, m, n0, t); return;+ }+#endif mont_mul(r, a, b, m, n0, n, t); } @@ -190,7 +198,7 @@ (void)scratch; (void)s2n; #endif-#ifdef CRYPTON_MONT_SQR+#ifdef CRYPTON_MONT_FIXED switch (n) { case 16: crypton_mont_sqr16(r, a, m, n0, t); return; case 24: crypton_mont_sqr24(r, a, m, n0, t); return;@@ -371,6 +379,10 @@ return n > 0; #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 */+ return n == 32; #else (void) n; return 0;@@ -387,7 +399,39 @@ const uint8_t *exp, uint32_t explen, const uint8_t *mod, uint32_t modlen) {+ return crypton_powm_pub_r2(out, base, baselen, exp, explen, mod, modlen, NULL);+}++int crypton_powm_r2(uint8_t *out, const uint8_t *mod, uint32_t modlen)+{ uint32_t n = (modlen + LIMB_BYTES - 1) / LIMB_BYTES;+ limb_t *space, *m, *r2, *t;++ if (modlen == 0 || n == 0 || (mod[modlen - 1] & 1) == 0 || !powm_pub_wanted(n))+ return 1;+ space = calloc(5 * n, sizeof(limb_t));+ if (space == NULL)+ return 1;+ m = space;+ r2 = m + n;+ t = r2 + n;+ if (from_be(m, n, mod, modlen) != 0) {+ free(space);+ return 1;+ }+ mont_r2(r2, m, mont_n0(m[0]), n, t);+ to_be(out, modlen, r2, n);+ free(space);+ return 0;+}++int crypton_powm_pub_r2(uint8_t *out,+ const uint8_t *base, uint32_t baselen,+ const uint8_t *exp, uint32_t explen,+ const uint8_t *mod, uint32_t modlen,+ const uint8_t *r2be)+{+ uint32_t n = (modlen + LIMB_BYTES - 1) / LIMB_BYTES; uint32_t words = (6 + 2) * n + powm_s2n_scratch(n); limb_t *space, *m, *r2, *acc, *tmp, *bm, *one, *t, *scratch, n0; uint32_t top, i;@@ -427,7 +471,10 @@ if (from_be(m, n, mod, modlen) != 0) goto fail; n0 = mont_n0(m[0]);- mont_r2(r2, m, n0, n, t);+ if (r2be == NULL)+ mont_r2(r2, m, n0, n, t);+ else if (from_be(r2, n, r2be, modlen) != 0)+ goto fail; /* the base into Montgomery form. The accumulator starts there rather * than at one, because the exponent's top bit is a one by
cbits/crypton_powm.h view
@@ -37,6 +37,33 @@ const uint8_t *exp, uint32_t explen, const uint8_t *mod, uint32_t modlen); +/* crypton_powm_pub with R^2 mod m given, big-endian in modlen bytes, as+ * crypton_powm_r2 computes it; NULL computes it here as crypton_powm_pub does.+ * A caller verifying under one key many times keeps it. */+int crypton_powm_pub_r2(uint8_t *out,+ const uint8_t *base, uint32_t baselen,+ const uint8_t *exp, uint32_t explen,+ const uint8_t *mod, uint32_t modlen,+ const uint8_t *r2be);++/* R^2 mod m for crypton_powm_pub_r2, or nonzero where crypton_powm_pub would+ * decline this modulus, so that nothing is kept for it. */+int crypton_powm_r2(uint8_t *out, const uint8_t *mod, uint32_t modlen);++/* Two secure exponentiations at once, as the halves of an RSA private-key+ * operation by CRT are: each as crypton_powm_sec, with the same contract.+ *+ * Only on x86-64 with AVX-512 IFMA, for two moduli of 128, 192 or 256 bytes+ * and two exponents of the same length. It declines everywhere else --+ * returning nonzero with both outputs untouched -- so a caller must have+ * crypton_powm_sec to fall back to. */+int crypton_powm_sec_x2(uint8_t *out1, const uint8_t *base1, uint32_t baselen1,+ const uint8_t *exp1, uint32_t explen1,+ const uint8_t *mod1, uint32_t modlen1,+ uint8_t *out2, const uint8_t *base2, uint32_t baselen2,+ const uint8_t *exp2, uint32_t explen2,+ const uint8_t *mod2, uint32_t modlen2);+ /* The window the secure exponentiation walks the exponent in, so that a * build which did not take -DPOWM_WINDOW_BITS cannot pass for one that * did. */
+ cbits/crypton_powm_ifma.c view
@@ -0,0 +1,187 @@+/* Two secure exponentiations at once with AVX-512 IFMA, the CRT halves of+ * RSA-2048, -3072 and -4096: crypton_powm_sec's walk with a five-bit window,+ * over the multiplication generated by cbits/crypton_powm_ifma.py. */+#include <stdlib.h>+#include <string.h>+#include <crypton_bignum.h>+#include <crypton_bzero.h>+#include <crypton_powm.h>++#if defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__))+#include <crypton_cpu.h>+#include "crypton_powm_ifma.h"++#define WIN 5++typedef void (*amm_fn)(uint64_t *, const uint64_t *, const uint64_t *, const uint64_t *,+ uint64_t, uint64_t *, const uint64_t *, const uint64_t *,+ const uint64_t *, uint64_t);+typedef void (*sel_fn)(uint64_t *, const uint64_t *, uint64_t, uint64_t *,+ const uint64_t *, uint64_t);++/* limbs of 64 bits to digits of 52, d of them; the rest of the w words zero */+static void to_digits(uint64_t *dg, uint32_t w, const limb_t *l, uint32_t n, uint32_t d)+{+ uint32_t i;++ memset(dg, 0, w * sizeof(uint64_t));+ for (i = 0; i < d; i++) {+ uint32_t bit = 52 * i, li = bit / 64, sh = bit % 64;+ uint64_t v = li < n ? l[li] >> sh : 0;++ if (sh > 12 && li + 1 < n)+ v |= l[li + 1] << (64 - sh);+ dg[i] = v & IFMA_MASK52;+ }+}++static void from_digits(limb_t *l, uint32_t n, const uint64_t *dg, uint32_t d)+{+ uint32_t i;++ memset(l, 0, n * sizeof(limb_t));+ for (i = 0; i < d; i++) {+ uint32_t bit = 52 * i, li = bit / 64, sh = bit % 64;++ if (li < n)+ l[li] |= dg[i] << sh;+ if (sh > 12 && li + 1 < n)+ l[li + 1] |= dg[i] >> (64 - sh);+ }+}++/* Window k from the bottom of a big-endian exponent of len bytes. Which+ * window is read is the loop counter's business, not the exponent's. */+static uint64_t window(const uint8_t *e, uint32_t len, uint32_t k)+{+ uint64_t v = 0;+ uint32_t j;++ for (j = 0; j < WIN; j++) {+ uint32_t bit = k * WIN + j;++ if (bit < 8 * len)+ v |= (uint64_t) ((e[len - 1 - bit / 8] >> (bit % 8)) & 1) << j;+ }+ return v;+}++/* m and k0 in digits, and R^2 mod m for R = 2^(52d): crypton's R^2 is for+ * 2^(64n), so it is doubled the rest of the way */+static int setup(const uint8_t *mod, uint32_t modlen, uint32_t n, uint32_t d, uint32_t w,+ limb_t *ml, uint64_t *md, uint64_t *rr, uint64_t *k0, limb_t *t)+{+ limb_t *r2 = t + 4 * n;+ uint32_t j;++ if (from_be(ml, n, mod, modlen) != 0 || (ml[0] & 1) == 0)+ return 1;+ *k0 = mont_n0(ml[0]);+ mont_r2(r2, ml, *k0, n, t);+ for (j = 0; j < 2 * (52 * d - 64 * n); j++)+ dbl_mod(r2, ml, n, t);+ to_digits(md, w, ml, n, d);+ to_digits(rr, w, r2, n, d);+ return 0;+}++int crypton_powm_sec_x2(uint8_t *out1, const uint8_t *base1, uint32_t baselen1,+ const uint8_t *exp1, uint32_t explen1,+ const uint8_t *mod1, uint32_t modlen1,+ uint8_t *out2, const uint8_t *base2, uint32_t baselen2,+ const uint8_t *exp2, uint32_t explen2,+ const uint8_t *mod2, uint32_t modlen2)+{+ uint32_t n, d, w, nwin, k, j;+ amm_fn amm;+ sel_fn sel;+ uint64_t *space, *m1, *m2, *rr1, *rr2, *x1, *x2, *s1, *s2, *one, *t1, *t2, k1, k2;+ limb_t *l1, *l2, *lt, *lt2;+ size_t words;++ if (modlen1 != modlen2 || explen1 != explen2)+ return 1;+ if ((crypton_x86_simd_features() & CRYPTON_X86_IFMA) == 0)+ return 1;+ switch (modlen1) {+ case 128: d = 20; amm = ifma_amm20_x2; sel = ifma_sel5; break;+ case 192: d = 30; amm = ifma_amm30_x2; sel = ifma_sel8; break;+ case 256: d = 40; amm = ifma_amm40_x2; sel = ifma_sel10; break;+ default: return 1;+ }+ n = modlen1 / 8;+ w = 4 * ((d + 3) / 4);++ /* nine numbers in digits, two tables of 32, and limbs for the setup */+ words = (size_t) w * (9 + 2 * 32) + (size_t) n * 12;+ space = calloc(words, sizeof(uint64_t));+ if (space == NULL)+ return 1;+ m1 = space; m2 = m1 + w; rr1 = m2 + w; rr2 = rr1 + w;+ x1 = rr2 + w; x2 = x1 + w; s1 = x2 + w; s2 = s1 + w; one = s2 + w;+ t1 = one + w; t2 = t1 + 32 * w;+ l1 = (limb_t *)(t2 + 32 * w); l2 = l1 + n; lt = l2 + n; lt2 = lt + n;++ if (setup(mod1, modlen1, n, d, w, l1, m1, rr1, &k1, lt) != 0+ || setup(mod2, modlen2, n, d, w, l2, m2, rr2, &k2, lt) != 0)+ goto fail;++ /* the bases, under their moduli as the contract says, into digits */+ if (from_be(lt, n, base1, baselen1) != 0 || from_be(lt2, n, base2, baselen2) != 0)+ goto fail;+ to_digits(s1, w, lt, n, d);+ to_digits(s2, w, lt2, n, d);++ /* table[0] = R and table[1] = b R in Montgomery form, table[k] = b^k R */+ one[0] = 1;+ amm(t1, one, rr1, m1, k1, t2, one, rr2, m2, k2);+ amm(t1 + w, s1, rr1, m1, k1, t2 + w, s2, rr2, m2, k2);+ for (k = 2; k < 32; k++)+ amm(t1 + k * w, t1 + (k - 1) * w, t1 + w, m1, k1,+ t2 + k * w, t2 + (k - 1) * w, t2 + w, m2, k2);++ memcpy(x1, t1, w * sizeof(uint64_t));+ memcpy(x2, t2, w * sizeof(uint64_t));+ nwin = (8 * explen1 + WIN - 1) / WIN;+ for (k = nwin; k > 0; k--) {+ for (j = 0; j < WIN; j++)+ amm(x1, x1, x1, m1, k1, x2, x2, x2, m2, k2);+ sel(s1, t1, window(exp1, explen1, k - 1), s2, t2, window(exp2, explen2, k - 1));+ amm(x1, x1, s1, m1, k1, x2, x2, s2, m2, k2);+ }++ /* out of Montgomery form, then under m with one masked subtraction */+ amm(x1, x1, one, m1, k1, x2, x2, one, m2, k2);+ from_digits(lt, n, x1, d);+ select_n(lt, lt2, lt, sub_n(lt2, lt, l1, n) ^ 1, n);+ to_be(out1, modlen1, lt, n);+ from_digits(lt, n, x2, d);+ select_n(lt, lt2, lt, sub_n(lt2, lt, l2, n) ^ 1, n);+ to_be(out2, modlen2, lt, n);++ crypton_bzero(space, words * sizeof(uint64_t));+ free(space);+ return 0;++fail:+ crypton_bzero(space, words * sizeof(uint64_t));+ free(space);+ return 1;+}++#else++int crypton_powm_sec_x2(uint8_t *out1, const uint8_t *base1, uint32_t baselen1,+ const uint8_t *exp1, uint32_t explen1,+ const uint8_t *mod1, uint32_t modlen1,+ uint8_t *out2, const uint8_t *base2, uint32_t baselen2,+ const uint8_t *exp2, uint32_t explen2,+ const uint8_t *mod2, uint32_t modlen2)+{+ (void) out1; (void) base1; (void) baselen1; (void) exp1; (void) explen1;+ (void) mod1; (void) modlen1; (void) out2; (void) base2; (void) baselen2;+ (void) exp2; (void) explen2; (void) mod2; (void) modlen2;+ return 1;+}++#endif
+ cbits/crypton_powm_ifma.h view
@@ -0,0 +1,513 @@+/* Generated by cbits/crypton_powm_ifma.py; do not edit.+ *+ * Almost-Montgomery multiplication in radix 2^52, two at once: r = a b+ * 2^-52D mod m, under 2m for a and b under 2m. Digits are 52 bits in 64-bit+ * words, each number padded with zero words to a whole number of 256-bit+ * registers. m is read from memory; at 20 digits a is held in registers,+ * above that it is read from memory too. */+#ifndef CRYPTON_POWM_IFMA_H+#define CRYPTON_POWM_IFMA_H++#include <stdint.h>+#include <immintrin.h>++#define IFMA_MASK52 ((UINT64_C(1) << 52) - 1)+#define IFMA_TARGET __attribute__((target("avx2,avx512f,avx512vl,avx512ifma")))++/* 20 lanes to 52-bit digits: what is above 52 bits moves up a lane,+ * and the one-bit carries that can then remain are resolved together */+IFMA_TARGET static inline void ifma_norm5(uint64_t *r, __m256i X0, __m256i X1, __m256i X2, __m256i X3, __m256i X4)+{+ const __m256i mk = _mm256_set1_epi64x((long long) IFMA_MASK52), one = _mm256_set1_epi64x(1);+ const __m256i zero = _mm256_setzero_si256();+ uint64_t g = 0, p = 0, c;+ __m256i C0 = _mm256_srli_epi64(X0, 52);+ __m256i C1 = _mm256_srli_epi64(X1, 52);+ __m256i C2 = _mm256_srli_epi64(X2, 52);+ __m256i C3 = _mm256_srli_epi64(X3, 52);+ __m256i C4 = _mm256_srli_epi64(X4, 52);+ X0 = _mm256_add_epi64(_mm256_and_si256(X0, mk), _mm256_alignr_epi64(C0, zero, 3));+ X1 = _mm256_add_epi64(_mm256_and_si256(X1, mk), _mm256_alignr_epi64(C1, C0, 3));+ X2 = _mm256_add_epi64(_mm256_and_si256(X2, mk), _mm256_alignr_epi64(C2, C1, 3));+ X3 = _mm256_add_epi64(_mm256_and_si256(X3, mk), _mm256_alignr_epi64(C3, C2, 3));+ X4 = _mm256_add_epi64(_mm256_and_si256(X4, mk), _mm256_alignr_epi64(C4, C3, 3));+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X0, mk) << 0;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X0, mk) << 0;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X1, mk) << 4;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X1, mk) << 4;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X2, mk) << 8;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X2, mk) << 8;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X3, mk) << 12;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X3, mk) << 12;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X4, mk) << 16;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X4, mk) << 16;+ c = ((g << 1) + p) ^ p;+ X0 = _mm256_and_si256(_mm256_mask_add_epi64(X0, (__mmask8)(c >> 0 & 15), X0, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 0), X0);+ X1 = _mm256_and_si256(_mm256_mask_add_epi64(X1, (__mmask8)(c >> 4 & 15), X1, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 4), X1);+ X2 = _mm256_and_si256(_mm256_mask_add_epi64(X2, (__mmask8)(c >> 8 & 15), X2, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 8), X2);+ X3 = _mm256_and_si256(_mm256_mask_add_epi64(X3, (__mmask8)(c >> 12 & 15), X3, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 12), X3);+ X4 = _mm256_and_si256(_mm256_mask_add_epi64(X4, (__mmask8)(c >> 16 & 15), X4, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 16), X4);+}++/* both tables' entries k1 and k2 of 32, every entry read and a mask keeping+ * one; entries are 20 words apart */+IFMA_TARGET static void ifma_sel5(uint64_t *o1, const uint64_t *t1, uint64_t k1,+ uint64_t *o2, const uint64_t *t2, uint64_t k2)+{+ const __m256i one = _mm256_set1_epi64x(1);+ __m256i v1 = _mm256_set1_epi64x((long long) k1), v2 = _mm256_set1_epi64x((long long) k2);+ __m256i kv = _mm256_setzero_si256();+ __m256i P0 = kv, Q0 = kv, P1 = kv, Q1 = kv, P2 = kv, Q2 = kv, P3 = kv, Q3 = kv, P4 = kv, Q4 = kv;+ int k;+ for (k = 0; k < 32; k++) {+ __mmask8 s1 = _mm256_cmpeq_epi64_mask(v1, kv), s2 = _mm256_cmpeq_epi64_mask(v2, kv);+ const uint64_t *e1 = t1 + 20 * k, *e2 = t2 + 20 * k;+ P0 = _mm256_mask_loadu_epi64(P0, s1, e1 + 0); Q0 = _mm256_mask_loadu_epi64(Q0, s2, e2 + 0);+ P1 = _mm256_mask_loadu_epi64(P1, s1, e1 + 4); Q1 = _mm256_mask_loadu_epi64(Q1, s2, e2 + 4);+ P2 = _mm256_mask_loadu_epi64(P2, s1, e1 + 8); Q2 = _mm256_mask_loadu_epi64(Q2, s2, e2 + 8);+ P3 = _mm256_mask_loadu_epi64(P3, s1, e1 + 12); Q3 = _mm256_mask_loadu_epi64(Q3, s2, e2 + 12);+ P4 = _mm256_mask_loadu_epi64(P4, s1, e1 + 16); Q4 = _mm256_mask_loadu_epi64(Q4, s2, e2 + 16);+ kv = _mm256_add_epi64(kv, one);+ }+ _mm256_storeu_si256((__m256i *)(o1 + 0), P0); _mm256_storeu_si256((__m256i *)(o2 + 0), Q0);+ _mm256_storeu_si256((__m256i *)(o1 + 4), P1); _mm256_storeu_si256((__m256i *)(o2 + 4), Q1);+ _mm256_storeu_si256((__m256i *)(o1 + 8), P2); _mm256_storeu_si256((__m256i *)(o2 + 8), Q2);+ _mm256_storeu_si256((__m256i *)(o1 + 12), P3); _mm256_storeu_si256((__m256i *)(o2 + 12), Q3);+ _mm256_storeu_si256((__m256i *)(o1 + 16), P4); _mm256_storeu_si256((__m256i *)(o2 + 16), Q4);+}++/* 32 lanes to 52-bit digits: what is above 52 bits moves up a lane,+ * and the one-bit carries that can then remain are resolved together */+IFMA_TARGET static inline void ifma_norm8(uint64_t *r, __m256i X0, __m256i X1, __m256i X2, __m256i X3, __m256i X4, __m256i X5, __m256i X6, __m256i X7)+{+ const __m256i mk = _mm256_set1_epi64x((long long) IFMA_MASK52), one = _mm256_set1_epi64x(1);+ const __m256i zero = _mm256_setzero_si256();+ uint64_t g = 0, p = 0, c;+ __m256i C0 = _mm256_srli_epi64(X0, 52);+ __m256i C1 = _mm256_srli_epi64(X1, 52);+ __m256i C2 = _mm256_srli_epi64(X2, 52);+ __m256i C3 = _mm256_srli_epi64(X3, 52);+ __m256i C4 = _mm256_srli_epi64(X4, 52);+ __m256i C5 = _mm256_srli_epi64(X5, 52);+ __m256i C6 = _mm256_srli_epi64(X6, 52);+ __m256i C7 = _mm256_srli_epi64(X7, 52);+ X0 = _mm256_add_epi64(_mm256_and_si256(X0, mk), _mm256_alignr_epi64(C0, zero, 3));+ X1 = _mm256_add_epi64(_mm256_and_si256(X1, mk), _mm256_alignr_epi64(C1, C0, 3));+ X2 = _mm256_add_epi64(_mm256_and_si256(X2, mk), _mm256_alignr_epi64(C2, C1, 3));+ X3 = _mm256_add_epi64(_mm256_and_si256(X3, mk), _mm256_alignr_epi64(C3, C2, 3));+ X4 = _mm256_add_epi64(_mm256_and_si256(X4, mk), _mm256_alignr_epi64(C4, C3, 3));+ X5 = _mm256_add_epi64(_mm256_and_si256(X5, mk), _mm256_alignr_epi64(C5, C4, 3));+ X6 = _mm256_add_epi64(_mm256_and_si256(X6, mk), _mm256_alignr_epi64(C6, C5, 3));+ X7 = _mm256_add_epi64(_mm256_and_si256(X7, mk), _mm256_alignr_epi64(C7, C6, 3));+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X0, mk) << 0;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X0, mk) << 0;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X1, mk) << 4;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X1, mk) << 4;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X2, mk) << 8;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X2, mk) << 8;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X3, mk) << 12;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X3, mk) << 12;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X4, mk) << 16;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X4, mk) << 16;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X5, mk) << 20;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X5, mk) << 20;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X6, mk) << 24;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X6, mk) << 24;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X7, mk) << 28;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X7, mk) << 28;+ c = ((g << 1) + p) ^ p;+ X0 = _mm256_and_si256(_mm256_mask_add_epi64(X0, (__mmask8)(c >> 0 & 15), X0, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 0), X0);+ X1 = _mm256_and_si256(_mm256_mask_add_epi64(X1, (__mmask8)(c >> 4 & 15), X1, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 4), X1);+ X2 = _mm256_and_si256(_mm256_mask_add_epi64(X2, (__mmask8)(c >> 8 & 15), X2, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 8), X2);+ X3 = _mm256_and_si256(_mm256_mask_add_epi64(X3, (__mmask8)(c >> 12 & 15), X3, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 12), X3);+ X4 = _mm256_and_si256(_mm256_mask_add_epi64(X4, (__mmask8)(c >> 16 & 15), X4, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 16), X4);+ X5 = _mm256_and_si256(_mm256_mask_add_epi64(X5, (__mmask8)(c >> 20 & 15), X5, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 20), X5);+ X6 = _mm256_and_si256(_mm256_mask_add_epi64(X6, (__mmask8)(c >> 24 & 15), X6, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 24), X6);+ X7 = _mm256_and_si256(_mm256_mask_add_epi64(X7, (__mmask8)(c >> 28 & 15), X7, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 28), X7);+}++/* both tables' entries k1 and k2 of 32, every entry read and a mask keeping+ * one; entries are 32 words apart */+IFMA_TARGET static void ifma_sel8(uint64_t *o1, const uint64_t *t1, uint64_t k1,+ uint64_t *o2, const uint64_t *t2, uint64_t k2)+{+ const __m256i one = _mm256_set1_epi64x(1);+ __m256i v1 = _mm256_set1_epi64x((long long) k1), v2 = _mm256_set1_epi64x((long long) k2);+ __m256i kv = _mm256_setzero_si256();+ __m256i P0 = kv, Q0 = kv, P1 = kv, Q1 = kv, P2 = kv, Q2 = kv, P3 = kv, Q3 = kv, P4 = kv, Q4 = kv, P5 = kv, Q5 = kv, P6 = kv, Q6 = kv, P7 = kv, Q7 = kv;+ int k;+ for (k = 0; k < 32; k++) {+ __mmask8 s1 = _mm256_cmpeq_epi64_mask(v1, kv), s2 = _mm256_cmpeq_epi64_mask(v2, kv);+ const uint64_t *e1 = t1 + 32 * k, *e2 = t2 + 32 * k;+ P0 = _mm256_mask_loadu_epi64(P0, s1, e1 + 0); Q0 = _mm256_mask_loadu_epi64(Q0, s2, e2 + 0);+ P1 = _mm256_mask_loadu_epi64(P1, s1, e1 + 4); Q1 = _mm256_mask_loadu_epi64(Q1, s2, e2 + 4);+ P2 = _mm256_mask_loadu_epi64(P2, s1, e1 + 8); Q2 = _mm256_mask_loadu_epi64(Q2, s2, e2 + 8);+ P3 = _mm256_mask_loadu_epi64(P3, s1, e1 + 12); Q3 = _mm256_mask_loadu_epi64(Q3, s2, e2 + 12);+ P4 = _mm256_mask_loadu_epi64(P4, s1, e1 + 16); Q4 = _mm256_mask_loadu_epi64(Q4, s2, e2 + 16);+ P5 = _mm256_mask_loadu_epi64(P5, s1, e1 + 20); Q5 = _mm256_mask_loadu_epi64(Q5, s2, e2 + 20);+ P6 = _mm256_mask_loadu_epi64(P6, s1, e1 + 24); Q6 = _mm256_mask_loadu_epi64(Q6, s2, e2 + 24);+ P7 = _mm256_mask_loadu_epi64(P7, s1, e1 + 28); Q7 = _mm256_mask_loadu_epi64(Q7, s2, e2 + 28);+ kv = _mm256_add_epi64(kv, one);+ }+ _mm256_storeu_si256((__m256i *)(o1 + 0), P0); _mm256_storeu_si256((__m256i *)(o2 + 0), Q0);+ _mm256_storeu_si256((__m256i *)(o1 + 4), P1); _mm256_storeu_si256((__m256i *)(o2 + 4), Q1);+ _mm256_storeu_si256((__m256i *)(o1 + 8), P2); _mm256_storeu_si256((__m256i *)(o2 + 8), Q2);+ _mm256_storeu_si256((__m256i *)(o1 + 12), P3); _mm256_storeu_si256((__m256i *)(o2 + 12), Q3);+ _mm256_storeu_si256((__m256i *)(o1 + 16), P4); _mm256_storeu_si256((__m256i *)(o2 + 16), Q4);+ _mm256_storeu_si256((__m256i *)(o1 + 20), P5); _mm256_storeu_si256((__m256i *)(o2 + 20), Q5);+ _mm256_storeu_si256((__m256i *)(o1 + 24), P6); _mm256_storeu_si256((__m256i *)(o2 + 24), Q6);+ _mm256_storeu_si256((__m256i *)(o1 + 28), P7); _mm256_storeu_si256((__m256i *)(o2 + 28), Q7);+}++/* 40 lanes to 52-bit digits: what is above 52 bits moves up a lane,+ * and the one-bit carries that can then remain are resolved together */+IFMA_TARGET static inline void ifma_norm10(uint64_t *r, __m256i X0, __m256i X1, __m256i X2, __m256i X3, __m256i X4, __m256i X5, __m256i X6, __m256i X7, __m256i X8, __m256i X9)+{+ const __m256i mk = _mm256_set1_epi64x((long long) IFMA_MASK52), one = _mm256_set1_epi64x(1);+ const __m256i zero = _mm256_setzero_si256();+ uint64_t g = 0, p = 0, c;+ __m256i C0 = _mm256_srli_epi64(X0, 52);+ __m256i C1 = _mm256_srli_epi64(X1, 52);+ __m256i C2 = _mm256_srli_epi64(X2, 52);+ __m256i C3 = _mm256_srli_epi64(X3, 52);+ __m256i C4 = _mm256_srli_epi64(X4, 52);+ __m256i C5 = _mm256_srli_epi64(X5, 52);+ __m256i C6 = _mm256_srli_epi64(X6, 52);+ __m256i C7 = _mm256_srli_epi64(X7, 52);+ __m256i C8 = _mm256_srli_epi64(X8, 52);+ __m256i C9 = _mm256_srli_epi64(X9, 52);+ X0 = _mm256_add_epi64(_mm256_and_si256(X0, mk), _mm256_alignr_epi64(C0, zero, 3));+ X1 = _mm256_add_epi64(_mm256_and_si256(X1, mk), _mm256_alignr_epi64(C1, C0, 3));+ X2 = _mm256_add_epi64(_mm256_and_si256(X2, mk), _mm256_alignr_epi64(C2, C1, 3));+ X3 = _mm256_add_epi64(_mm256_and_si256(X3, mk), _mm256_alignr_epi64(C3, C2, 3));+ X4 = _mm256_add_epi64(_mm256_and_si256(X4, mk), _mm256_alignr_epi64(C4, C3, 3));+ X5 = _mm256_add_epi64(_mm256_and_si256(X5, mk), _mm256_alignr_epi64(C5, C4, 3));+ X6 = _mm256_add_epi64(_mm256_and_si256(X6, mk), _mm256_alignr_epi64(C6, C5, 3));+ X7 = _mm256_add_epi64(_mm256_and_si256(X7, mk), _mm256_alignr_epi64(C7, C6, 3));+ X8 = _mm256_add_epi64(_mm256_and_si256(X8, mk), _mm256_alignr_epi64(C8, C7, 3));+ X9 = _mm256_add_epi64(_mm256_and_si256(X9, mk), _mm256_alignr_epi64(C9, C8, 3));+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X0, mk) << 0;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X0, mk) << 0;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X1, mk) << 4;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X1, mk) << 4;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X2, mk) << 8;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X2, mk) << 8;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X3, mk) << 12;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X3, mk) << 12;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X4, mk) << 16;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X4, mk) << 16;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X5, mk) << 20;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X5, mk) << 20;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X6, mk) << 24;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X6, mk) << 24;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X7, mk) << 28;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X7, mk) << 28;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X8, mk) << 32;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X8, mk) << 32;+ g |= (uint64_t) _mm256_cmpgt_epu64_mask(X9, mk) << 36;+ p |= (uint64_t) _mm256_cmpeq_epu64_mask(X9, mk) << 36;+ c = ((g << 1) + p) ^ p;+ X0 = _mm256_and_si256(_mm256_mask_add_epi64(X0, (__mmask8)(c >> 0 & 15), X0, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 0), X0);+ X1 = _mm256_and_si256(_mm256_mask_add_epi64(X1, (__mmask8)(c >> 4 & 15), X1, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 4), X1);+ X2 = _mm256_and_si256(_mm256_mask_add_epi64(X2, (__mmask8)(c >> 8 & 15), X2, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 8), X2);+ X3 = _mm256_and_si256(_mm256_mask_add_epi64(X3, (__mmask8)(c >> 12 & 15), X3, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 12), X3);+ X4 = _mm256_and_si256(_mm256_mask_add_epi64(X4, (__mmask8)(c >> 16 & 15), X4, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 16), X4);+ X5 = _mm256_and_si256(_mm256_mask_add_epi64(X5, (__mmask8)(c >> 20 & 15), X5, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 20), X5);+ X6 = _mm256_and_si256(_mm256_mask_add_epi64(X6, (__mmask8)(c >> 24 & 15), X6, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 24), X6);+ X7 = _mm256_and_si256(_mm256_mask_add_epi64(X7, (__mmask8)(c >> 28 & 15), X7, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 28), X7);+ X8 = _mm256_and_si256(_mm256_mask_add_epi64(X8, (__mmask8)(c >> 32 & 15), X8, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 32), X8);+ X9 = _mm256_and_si256(_mm256_mask_add_epi64(X9, (__mmask8)(c >> 36 & 15), X9, one), mk);+ _mm256_storeu_si256((__m256i *)(r + 36), X9);+}++/* both tables' entries k1 and k2 of 32, every entry read and a mask keeping+ * one; entries are 40 words apart */+IFMA_TARGET static void ifma_sel10(uint64_t *o1, const uint64_t *t1, uint64_t k1,+ uint64_t *o2, const uint64_t *t2, uint64_t k2)+{+ const __m256i one = _mm256_set1_epi64x(1);+ __m256i v1 = _mm256_set1_epi64x((long long) k1), v2 = _mm256_set1_epi64x((long long) k2);+ __m256i kv = _mm256_setzero_si256();+ __m256i P0 = kv, Q0 = kv, P1 = kv, Q1 = kv, P2 = kv, Q2 = kv, P3 = kv, Q3 = kv, P4 = kv, Q4 = kv, P5 = kv, Q5 = kv, P6 = kv, Q6 = kv, P7 = kv, Q7 = kv, P8 = kv, Q8 = kv, P9 = kv, Q9 = kv;+ int k;+ for (k = 0; k < 32; k++) {+ __mmask8 s1 = _mm256_cmpeq_epi64_mask(v1, kv), s2 = _mm256_cmpeq_epi64_mask(v2, kv);+ const uint64_t *e1 = t1 + 40 * k, *e2 = t2 + 40 * k;+ P0 = _mm256_mask_loadu_epi64(P0, s1, e1 + 0); Q0 = _mm256_mask_loadu_epi64(Q0, s2, e2 + 0);+ P1 = _mm256_mask_loadu_epi64(P1, s1, e1 + 4); Q1 = _mm256_mask_loadu_epi64(Q1, s2, e2 + 4);+ P2 = _mm256_mask_loadu_epi64(P2, s1, e1 + 8); Q2 = _mm256_mask_loadu_epi64(Q2, s2, e2 + 8);+ P3 = _mm256_mask_loadu_epi64(P3, s1, e1 + 12); Q3 = _mm256_mask_loadu_epi64(Q3, s2, e2 + 12);+ P4 = _mm256_mask_loadu_epi64(P4, s1, e1 + 16); Q4 = _mm256_mask_loadu_epi64(Q4, s2, e2 + 16);+ P5 = _mm256_mask_loadu_epi64(P5, s1, e1 + 20); Q5 = _mm256_mask_loadu_epi64(Q5, s2, e2 + 20);+ P6 = _mm256_mask_loadu_epi64(P6, s1, e1 + 24); Q6 = _mm256_mask_loadu_epi64(Q6, s2, e2 + 24);+ P7 = _mm256_mask_loadu_epi64(P7, s1, e1 + 28); Q7 = _mm256_mask_loadu_epi64(Q7, s2, e2 + 28);+ P8 = _mm256_mask_loadu_epi64(P8, s1, e1 + 32); Q8 = _mm256_mask_loadu_epi64(Q8, s2, e2 + 32);+ P9 = _mm256_mask_loadu_epi64(P9, s1, e1 + 36); Q9 = _mm256_mask_loadu_epi64(Q9, s2, e2 + 36);+ kv = _mm256_add_epi64(kv, one);+ }+ _mm256_storeu_si256((__m256i *)(o1 + 0), P0); _mm256_storeu_si256((__m256i *)(o2 + 0), Q0);+ _mm256_storeu_si256((__m256i *)(o1 + 4), P1); _mm256_storeu_si256((__m256i *)(o2 + 4), Q1);+ _mm256_storeu_si256((__m256i *)(o1 + 8), P2); _mm256_storeu_si256((__m256i *)(o2 + 8), Q2);+ _mm256_storeu_si256((__m256i *)(o1 + 12), P3); _mm256_storeu_si256((__m256i *)(o2 + 12), Q3);+ _mm256_storeu_si256((__m256i *)(o1 + 16), P4); _mm256_storeu_si256((__m256i *)(o2 + 16), Q4);+ _mm256_storeu_si256((__m256i *)(o1 + 20), P5); _mm256_storeu_si256((__m256i *)(o2 + 20), Q5);+ _mm256_storeu_si256((__m256i *)(o1 + 24), P6); _mm256_storeu_si256((__m256i *)(o2 + 24), Q6);+ _mm256_storeu_si256((__m256i *)(o1 + 28), P7); _mm256_storeu_si256((__m256i *)(o2 + 28), Q7);+ _mm256_storeu_si256((__m256i *)(o1 + 32), P8); _mm256_storeu_si256((__m256i *)(o2 + 32), Q8);+ _mm256_storeu_si256((__m256i *)(o1 + 36), P9); _mm256_storeu_si256((__m256i *)(o2 + 36), Q9);+}++/* 20 digits, 5 registers a number */+IFMA_TARGET static void ifma_amm20_x2(uint64_t *r1, const uint64_t *a1, const uint64_t *b1,+ const uint64_t *m1, uint64_t k1,+ uint64_t *r2, const uint64_t *a2, const uint64_t *b2,+ const uint64_t *m2, uint64_t k2)+{+ const __m256i zero = _mm256_setzero_si256();+#define L(p, k) _mm256_loadu_si256((const __m256i *)((p) + 4 * (k)))+ __m256i X0 = zero, X1 = zero, X2 = zero, X3 = zero, X4 = zero, Y0 = zero, Y1 = zero, Y2 = zero, Y3 = zero, Y4 = zero;+ __m256i A0 = L(a1, 0), A1 = L(a1, 1), A2 = L(a1, 2), A3 = L(a1, 3), A4 = L(a1, 4);+ __m256i B0 = L(a2, 0), B1 = L(a2, 1), B2 = L(a2, 2), B3 = L(a2, 3), B4 = L(a2, 4);+ uint64_t x1 = 0, x2 = 0;+ int i;++ for (i = 0; i < 20; i++) {+ uint64_t bi = b1[i], ci = b2[i], y, z;+ /* lane 0 in full: the products' high halves, which are lane 1's, too */+ unsigned __int128 s1 = (unsigned __int128) a1[0] * bi + x1;+ unsigned __int128 s2 = (unsigned __int128) a2[0] * ci + x2;+ __m256i bv = _mm256_set1_epi64x((long long) bi), cv = _mm256_set1_epi64x((long long) ci);+ __m256i yv, zv;++ y = ((uint64_t) s1 * k1) & IFMA_MASK52;+ z = ((uint64_t) s2 * k2) & IFMA_MASK52;+ s1 += (unsigned __int128) m1[0] * y;+ s2 += (unsigned __int128) m2[0] * z;+ yv = _mm256_set1_epi64x((long long) y);+ zv = _mm256_set1_epi64x((long long) z);+ X0 = _mm256_madd52lo_epu64(X0, A0, bv); Y0 = _mm256_madd52lo_epu64(Y0, B0, cv);+ X1 = _mm256_madd52lo_epu64(X1, A1, bv); Y1 = _mm256_madd52lo_epu64(Y1, B1, cv);+ X2 = _mm256_madd52lo_epu64(X2, A2, bv); Y2 = _mm256_madd52lo_epu64(Y2, B2, cv);+ X3 = _mm256_madd52lo_epu64(X3, A3, bv); Y3 = _mm256_madd52lo_epu64(Y3, B3, cv);+ X4 = _mm256_madd52lo_epu64(X4, A4, bv); Y4 = _mm256_madd52lo_epu64(Y4, B4, cv);+ X0 = _mm256_madd52lo_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52lo_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52lo_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52lo_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52lo_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52lo_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52lo_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52lo_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52lo_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52lo_epu64(Y4, L(m2, 4), zv);+ /* down a lane: lane 0 is a multiple of 2^52, and s carries it */+ X0 = _mm256_alignr_epi64(X1, X0, 1); Y0 = _mm256_alignr_epi64(Y1, Y0, 1);+ X1 = _mm256_alignr_epi64(X2, X1, 1); Y1 = _mm256_alignr_epi64(Y2, Y1, 1);+ X2 = _mm256_alignr_epi64(X3, X2, 1); Y2 = _mm256_alignr_epi64(Y3, Y2, 1);+ X3 = _mm256_alignr_epi64(X4, X3, 1); Y3 = _mm256_alignr_epi64(Y4, Y3, 1);+ X4 = _mm256_alignr_epi64(zero, X4, 1); Y4 = _mm256_alignr_epi64(zero, Y4, 1);+ x1 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(X0)) + (uint64_t)(s1 >> 52);+ x2 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(Y0)) + (uint64_t)(s2 >> 52);+ X0 = _mm256_madd52hi_epu64(X0, A0, bv); Y0 = _mm256_madd52hi_epu64(Y0, B0, cv);+ X1 = _mm256_madd52hi_epu64(X1, A1, bv); Y1 = _mm256_madd52hi_epu64(Y1, B1, cv);+ X2 = _mm256_madd52hi_epu64(X2, A2, bv); Y2 = _mm256_madd52hi_epu64(Y2, B2, cv);+ X3 = _mm256_madd52hi_epu64(X3, A3, bv); Y3 = _mm256_madd52hi_epu64(Y3, B3, cv);+ X4 = _mm256_madd52hi_epu64(X4, A4, bv); Y4 = _mm256_madd52hi_epu64(Y4, B4, cv);+ X0 = _mm256_madd52hi_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52hi_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52hi_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52hi_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52hi_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52hi_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52hi_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52hi_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52hi_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52hi_epu64(Y4, L(m2, 4), zv);+ }+#undef L+ /* lane 0, with the carry it was never given, is what the scalar holds */+ X0 = _mm256_mask_set1_epi64(X0, 1, (long long) x1);+ Y0 = _mm256_mask_set1_epi64(Y0, 1, (long long) x2);+ ifma_norm5(r1, X0, X1, X2, X3, X4);+ ifma_norm5(r2, Y0, Y1, Y2, Y3, Y4);+}++/* 30 digits, 8 registers a number */+IFMA_TARGET static void ifma_amm30_x2(uint64_t *r1, const uint64_t *a1, const uint64_t *b1,+ const uint64_t *m1, uint64_t k1,+ uint64_t *r2, const uint64_t *a2, const uint64_t *b2,+ const uint64_t *m2, uint64_t k2)+{+ const __m256i zero = _mm256_setzero_si256();+#define L(p, k) _mm256_loadu_si256((const __m256i *)((p) + 4 * (k)))+ __m256i X0 = zero, X1 = zero, X2 = zero, X3 = zero, X4 = zero, X5 = zero, X6 = zero, X7 = zero, Y0 = zero, Y1 = zero, Y2 = zero, Y3 = zero, Y4 = zero, Y5 = zero, Y6 = zero, Y7 = zero;+ uint64_t x1 = 0, x2 = 0;+ int i;++ for (i = 0; i < 30; i++) {+ uint64_t bi = b1[i], ci = b2[i], y, z;+ /* lane 0 in full: the products' high halves, which are lane 1's, too */+ unsigned __int128 s1 = (unsigned __int128) a1[0] * bi + x1;+ unsigned __int128 s2 = (unsigned __int128) a2[0] * ci + x2;+ __m256i bv = _mm256_set1_epi64x((long long) bi), cv = _mm256_set1_epi64x((long long) ci);+ __m256i yv, zv;++ y = ((uint64_t) s1 * k1) & IFMA_MASK52;+ z = ((uint64_t) s2 * k2) & IFMA_MASK52;+ s1 += (unsigned __int128) m1[0] * y;+ s2 += (unsigned __int128) m2[0] * z;+ yv = _mm256_set1_epi64x((long long) y);+ zv = _mm256_set1_epi64x((long long) z);+ X0 = _mm256_madd52lo_epu64(X0, L(a1, 0), bv); Y0 = _mm256_madd52lo_epu64(Y0, L(a2, 0), cv);+ X1 = _mm256_madd52lo_epu64(X1, L(a1, 1), bv); Y1 = _mm256_madd52lo_epu64(Y1, L(a2, 1), cv);+ X2 = _mm256_madd52lo_epu64(X2, L(a1, 2), bv); Y2 = _mm256_madd52lo_epu64(Y2, L(a2, 2), cv);+ X3 = _mm256_madd52lo_epu64(X3, L(a1, 3), bv); Y3 = _mm256_madd52lo_epu64(Y3, L(a2, 3), cv);+ X4 = _mm256_madd52lo_epu64(X4, L(a1, 4), bv); Y4 = _mm256_madd52lo_epu64(Y4, L(a2, 4), cv);+ X5 = _mm256_madd52lo_epu64(X5, L(a1, 5), bv); Y5 = _mm256_madd52lo_epu64(Y5, L(a2, 5), cv);+ X6 = _mm256_madd52lo_epu64(X6, L(a1, 6), bv); Y6 = _mm256_madd52lo_epu64(Y6, L(a2, 6), cv);+ X7 = _mm256_madd52lo_epu64(X7, L(a1, 7), bv); Y7 = _mm256_madd52lo_epu64(Y7, L(a2, 7), cv);+ X0 = _mm256_madd52lo_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52lo_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52lo_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52lo_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52lo_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52lo_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52lo_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52lo_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52lo_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52lo_epu64(Y4, L(m2, 4), zv);+ X5 = _mm256_madd52lo_epu64(X5, L(m1, 5), yv); Y5 = _mm256_madd52lo_epu64(Y5, L(m2, 5), zv);+ X6 = _mm256_madd52lo_epu64(X6, L(m1, 6), yv); Y6 = _mm256_madd52lo_epu64(Y6, L(m2, 6), zv);+ X7 = _mm256_madd52lo_epu64(X7, L(m1, 7), yv); Y7 = _mm256_madd52lo_epu64(Y7, L(m2, 7), zv);+ /* down a lane: lane 0 is a multiple of 2^52, and s carries it */+ X0 = _mm256_alignr_epi64(X1, X0, 1); Y0 = _mm256_alignr_epi64(Y1, Y0, 1);+ X1 = _mm256_alignr_epi64(X2, X1, 1); Y1 = _mm256_alignr_epi64(Y2, Y1, 1);+ X2 = _mm256_alignr_epi64(X3, X2, 1); Y2 = _mm256_alignr_epi64(Y3, Y2, 1);+ X3 = _mm256_alignr_epi64(X4, X3, 1); Y3 = _mm256_alignr_epi64(Y4, Y3, 1);+ X4 = _mm256_alignr_epi64(X5, X4, 1); Y4 = _mm256_alignr_epi64(Y5, Y4, 1);+ X5 = _mm256_alignr_epi64(X6, X5, 1); Y5 = _mm256_alignr_epi64(Y6, Y5, 1);+ X6 = _mm256_alignr_epi64(X7, X6, 1); Y6 = _mm256_alignr_epi64(Y7, Y6, 1);+ X7 = _mm256_alignr_epi64(zero, X7, 1); Y7 = _mm256_alignr_epi64(zero, Y7, 1);+ x1 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(X0)) + (uint64_t)(s1 >> 52);+ x2 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(Y0)) + (uint64_t)(s2 >> 52);+ X0 = _mm256_madd52hi_epu64(X0, L(a1, 0), bv); Y0 = _mm256_madd52hi_epu64(Y0, L(a2, 0), cv);+ X1 = _mm256_madd52hi_epu64(X1, L(a1, 1), bv); Y1 = _mm256_madd52hi_epu64(Y1, L(a2, 1), cv);+ X2 = _mm256_madd52hi_epu64(X2, L(a1, 2), bv); Y2 = _mm256_madd52hi_epu64(Y2, L(a2, 2), cv);+ X3 = _mm256_madd52hi_epu64(X3, L(a1, 3), bv); Y3 = _mm256_madd52hi_epu64(Y3, L(a2, 3), cv);+ X4 = _mm256_madd52hi_epu64(X4, L(a1, 4), bv); Y4 = _mm256_madd52hi_epu64(Y4, L(a2, 4), cv);+ X5 = _mm256_madd52hi_epu64(X5, L(a1, 5), bv); Y5 = _mm256_madd52hi_epu64(Y5, L(a2, 5), cv);+ X6 = _mm256_madd52hi_epu64(X6, L(a1, 6), bv); Y6 = _mm256_madd52hi_epu64(Y6, L(a2, 6), cv);+ X7 = _mm256_madd52hi_epu64(X7, L(a1, 7), bv); Y7 = _mm256_madd52hi_epu64(Y7, L(a2, 7), cv);+ X0 = _mm256_madd52hi_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52hi_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52hi_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52hi_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52hi_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52hi_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52hi_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52hi_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52hi_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52hi_epu64(Y4, L(m2, 4), zv);+ X5 = _mm256_madd52hi_epu64(X5, L(m1, 5), yv); Y5 = _mm256_madd52hi_epu64(Y5, L(m2, 5), zv);+ X6 = _mm256_madd52hi_epu64(X6, L(m1, 6), yv); Y6 = _mm256_madd52hi_epu64(Y6, L(m2, 6), zv);+ X7 = _mm256_madd52hi_epu64(X7, L(m1, 7), yv); Y7 = _mm256_madd52hi_epu64(Y7, L(m2, 7), zv);+ }+#undef L+ /* lane 0, with the carry it was never given, is what the scalar holds */+ X0 = _mm256_mask_set1_epi64(X0, 1, (long long) x1);+ Y0 = _mm256_mask_set1_epi64(Y0, 1, (long long) x2);+ ifma_norm8(r1, X0, X1, X2, X3, X4, X5, X6, X7);+ ifma_norm8(r2, Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7);+}++/* 40 digits, 10 registers a number */+IFMA_TARGET static void ifma_amm40_x2(uint64_t *r1, const uint64_t *a1, const uint64_t *b1,+ const uint64_t *m1, uint64_t k1,+ uint64_t *r2, const uint64_t *a2, const uint64_t *b2,+ const uint64_t *m2, uint64_t k2)+{+ const __m256i zero = _mm256_setzero_si256();+#define L(p, k) _mm256_loadu_si256((const __m256i *)((p) + 4 * (k)))+ __m256i X0 = zero, X1 = zero, X2 = zero, X3 = zero, X4 = zero, X5 = zero, X6 = zero, X7 = zero, X8 = zero, X9 = zero, Y0 = zero, Y1 = zero, Y2 = zero, Y3 = zero, Y4 = zero, Y5 = zero, Y6 = zero, Y7 = zero, Y8 = zero, Y9 = zero;+ uint64_t x1 = 0, x2 = 0;+ int i;++ for (i = 0; i < 40; i++) {+ uint64_t bi = b1[i], ci = b2[i], y, z;+ /* lane 0 in full: the products' high halves, which are lane 1's, too */+ unsigned __int128 s1 = (unsigned __int128) a1[0] * bi + x1;+ unsigned __int128 s2 = (unsigned __int128) a2[0] * ci + x2;+ __m256i bv = _mm256_set1_epi64x((long long) bi), cv = _mm256_set1_epi64x((long long) ci);+ __m256i yv, zv;++ y = ((uint64_t) s1 * k1) & IFMA_MASK52;+ z = ((uint64_t) s2 * k2) & IFMA_MASK52;+ s1 += (unsigned __int128) m1[0] * y;+ s2 += (unsigned __int128) m2[0] * z;+ yv = _mm256_set1_epi64x((long long) y);+ zv = _mm256_set1_epi64x((long long) z);+ X0 = _mm256_madd52lo_epu64(X0, L(a1, 0), bv); Y0 = _mm256_madd52lo_epu64(Y0, L(a2, 0), cv);+ X1 = _mm256_madd52lo_epu64(X1, L(a1, 1), bv); Y1 = _mm256_madd52lo_epu64(Y1, L(a2, 1), cv);+ X2 = _mm256_madd52lo_epu64(X2, L(a1, 2), bv); Y2 = _mm256_madd52lo_epu64(Y2, L(a2, 2), cv);+ X3 = _mm256_madd52lo_epu64(X3, L(a1, 3), bv); Y3 = _mm256_madd52lo_epu64(Y3, L(a2, 3), cv);+ X4 = _mm256_madd52lo_epu64(X4, L(a1, 4), bv); Y4 = _mm256_madd52lo_epu64(Y4, L(a2, 4), cv);+ X5 = _mm256_madd52lo_epu64(X5, L(a1, 5), bv); Y5 = _mm256_madd52lo_epu64(Y5, L(a2, 5), cv);+ X6 = _mm256_madd52lo_epu64(X6, L(a1, 6), bv); Y6 = _mm256_madd52lo_epu64(Y6, L(a2, 6), cv);+ X7 = _mm256_madd52lo_epu64(X7, L(a1, 7), bv); Y7 = _mm256_madd52lo_epu64(Y7, L(a2, 7), cv);+ X8 = _mm256_madd52lo_epu64(X8, L(a1, 8), bv); Y8 = _mm256_madd52lo_epu64(Y8, L(a2, 8), cv);+ X9 = _mm256_madd52lo_epu64(X9, L(a1, 9), bv); Y9 = _mm256_madd52lo_epu64(Y9, L(a2, 9), cv);+ X0 = _mm256_madd52lo_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52lo_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52lo_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52lo_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52lo_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52lo_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52lo_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52lo_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52lo_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52lo_epu64(Y4, L(m2, 4), zv);+ X5 = _mm256_madd52lo_epu64(X5, L(m1, 5), yv); Y5 = _mm256_madd52lo_epu64(Y5, L(m2, 5), zv);+ X6 = _mm256_madd52lo_epu64(X6, L(m1, 6), yv); Y6 = _mm256_madd52lo_epu64(Y6, L(m2, 6), zv);+ X7 = _mm256_madd52lo_epu64(X7, L(m1, 7), yv); Y7 = _mm256_madd52lo_epu64(Y7, L(m2, 7), zv);+ X8 = _mm256_madd52lo_epu64(X8, L(m1, 8), yv); Y8 = _mm256_madd52lo_epu64(Y8, L(m2, 8), zv);+ X9 = _mm256_madd52lo_epu64(X9, L(m1, 9), yv); Y9 = _mm256_madd52lo_epu64(Y9, L(m2, 9), zv);+ /* down a lane: lane 0 is a multiple of 2^52, and s carries it */+ X0 = _mm256_alignr_epi64(X1, X0, 1); Y0 = _mm256_alignr_epi64(Y1, Y0, 1);+ X1 = _mm256_alignr_epi64(X2, X1, 1); Y1 = _mm256_alignr_epi64(Y2, Y1, 1);+ X2 = _mm256_alignr_epi64(X3, X2, 1); Y2 = _mm256_alignr_epi64(Y3, Y2, 1);+ X3 = _mm256_alignr_epi64(X4, X3, 1); Y3 = _mm256_alignr_epi64(Y4, Y3, 1);+ X4 = _mm256_alignr_epi64(X5, X4, 1); Y4 = _mm256_alignr_epi64(Y5, Y4, 1);+ X5 = _mm256_alignr_epi64(X6, X5, 1); Y5 = _mm256_alignr_epi64(Y6, Y5, 1);+ X6 = _mm256_alignr_epi64(X7, X6, 1); Y6 = _mm256_alignr_epi64(Y7, Y6, 1);+ X7 = _mm256_alignr_epi64(X8, X7, 1); Y7 = _mm256_alignr_epi64(Y8, Y7, 1);+ X8 = _mm256_alignr_epi64(X9, X8, 1); Y8 = _mm256_alignr_epi64(Y9, Y8, 1);+ X9 = _mm256_alignr_epi64(zero, X9, 1); Y9 = _mm256_alignr_epi64(zero, Y9, 1);+ x1 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(X0)) + (uint64_t)(s1 >> 52);+ x2 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(Y0)) + (uint64_t)(s2 >> 52);+ X0 = _mm256_madd52hi_epu64(X0, L(a1, 0), bv); Y0 = _mm256_madd52hi_epu64(Y0, L(a2, 0), cv);+ X1 = _mm256_madd52hi_epu64(X1, L(a1, 1), bv); Y1 = _mm256_madd52hi_epu64(Y1, L(a2, 1), cv);+ X2 = _mm256_madd52hi_epu64(X2, L(a1, 2), bv); Y2 = _mm256_madd52hi_epu64(Y2, L(a2, 2), cv);+ X3 = _mm256_madd52hi_epu64(X3, L(a1, 3), bv); Y3 = _mm256_madd52hi_epu64(Y3, L(a2, 3), cv);+ X4 = _mm256_madd52hi_epu64(X4, L(a1, 4), bv); Y4 = _mm256_madd52hi_epu64(Y4, L(a2, 4), cv);+ X5 = _mm256_madd52hi_epu64(X5, L(a1, 5), bv); Y5 = _mm256_madd52hi_epu64(Y5, L(a2, 5), cv);+ X6 = _mm256_madd52hi_epu64(X6, L(a1, 6), bv); Y6 = _mm256_madd52hi_epu64(Y6, L(a2, 6), cv);+ X7 = _mm256_madd52hi_epu64(X7, L(a1, 7), bv); Y7 = _mm256_madd52hi_epu64(Y7, L(a2, 7), cv);+ X8 = _mm256_madd52hi_epu64(X8, L(a1, 8), bv); Y8 = _mm256_madd52hi_epu64(Y8, L(a2, 8), cv);+ X9 = _mm256_madd52hi_epu64(X9, L(a1, 9), bv); Y9 = _mm256_madd52hi_epu64(Y9, L(a2, 9), cv);+ X0 = _mm256_madd52hi_epu64(X0, L(m1, 0), yv); Y0 = _mm256_madd52hi_epu64(Y0, L(m2, 0), zv);+ X1 = _mm256_madd52hi_epu64(X1, L(m1, 1), yv); Y1 = _mm256_madd52hi_epu64(Y1, L(m2, 1), zv);+ X2 = _mm256_madd52hi_epu64(X2, L(m1, 2), yv); Y2 = _mm256_madd52hi_epu64(Y2, L(m2, 2), zv);+ X3 = _mm256_madd52hi_epu64(X3, L(m1, 3), yv); Y3 = _mm256_madd52hi_epu64(Y3, L(m2, 3), zv);+ X4 = _mm256_madd52hi_epu64(X4, L(m1, 4), yv); Y4 = _mm256_madd52hi_epu64(Y4, L(m2, 4), zv);+ X5 = _mm256_madd52hi_epu64(X5, L(m1, 5), yv); Y5 = _mm256_madd52hi_epu64(Y5, L(m2, 5), zv);+ X6 = _mm256_madd52hi_epu64(X6, L(m1, 6), yv); Y6 = _mm256_madd52hi_epu64(Y6, L(m2, 6), zv);+ X7 = _mm256_madd52hi_epu64(X7, L(m1, 7), yv); Y7 = _mm256_madd52hi_epu64(Y7, L(m2, 7), zv);+ X8 = _mm256_madd52hi_epu64(X8, L(m1, 8), yv); Y8 = _mm256_madd52hi_epu64(Y8, L(m2, 8), zv);+ X9 = _mm256_madd52hi_epu64(X9, L(m1, 9), yv); Y9 = _mm256_madd52hi_epu64(Y9, L(m2, 9), zv);+ }+#undef L+ /* lane 0, with the carry it was never given, is what the scalar holds */+ X0 = _mm256_mask_set1_epi64(X0, 1, (long long) x1);+ Y0 = _mm256_mask_set1_epi64(Y0, 1, (long long) x2);+ ifma_norm10(r1, X0, X1, X2, X3, X4, X5, X6, X7, X8, X9);+ ifma_norm10(r2, Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9);+}++#endif
+ cbits/crypton_powm_ifma.py view
@@ -0,0 +1,178 @@+#!/usr/bin/env python3+"""Generate cbits/crypton_powm_ifma.h: two almost-Montgomery multiplications+at once in radix 2^52 with AVX-512 IFMA on 256-bit registers, at 20, 30 and+40 digits. Usage: python3 cbits/crypton_powm_ifma.py > cbits/crypton_powm_ifma.h++Gueron and Krasnov's method, a digit of b at a time. Lane 0 is followed in+full in a scalar, so it is read before the high halves go in and they stay+off the chain the next digit waits on.+"""++SIZES = (20, 30, 40)++HEADER = """\+/* Generated by cbits/crypton_powm_ifma.py; do not edit.+ *+ * Almost-Montgomery multiplication in radix 2^52, two at once: r = a b+ * 2^-52D mod m, under 2m for a and b under 2m. Digits are 52 bits in 64-bit+ * words, each number padded with zero words to a whole number of 256-bit+ * registers. m is read from memory; at 20 digits a is held in registers,+ * above that it is read from memory too. */+#ifndef CRYPTON_POWM_IFMA_H+#define CRYPTON_POWM_IFMA_H++#include <stdint.h>+#include <immintrin.h>++#define IFMA_MASK52 ((UINT64_C(1) << 52) - 1)+#define IFMA_TARGET __attribute__((target("avx2,avx512f,avx512vl,avx512ifma")))+"""++FOOTER = """\+#endif+"""+++def regs(d):+ return (d + 3) // 4+++def gen_norm(R):+ o = []+ w = o.append+ xs = [f"X{j}" for j in range(R)]+ w(f"/* {4 * R} lanes to 52-bit digits: what is above 52 bits moves up a lane,")+ w(f" * and the one-bit carries that can then remain are resolved together */")+ w(f"IFMA_TARGET static inline void ifma_norm{R}(uint64_t *r, " ++ ", ".join(f"__m256i {x}" for x in xs) + ")")+ w("{")+ w("\tconst __m256i mk = _mm256_set1_epi64x((long long) IFMA_MASK52), one = _mm256_set1_epi64x(1);")+ w("\tconst __m256i zero = _mm256_setzero_si256();")+ w("\tuint64_t g = 0, p = 0, c;")+ for j in range(R):+ w(f"\t__m256i C{j} = _mm256_srli_epi64(X{j}, 52);")+ for j in range(R):+ prev = f"C{j - 1}" if j else "zero"+ w(f"\tX{j} = _mm256_add_epi64(_mm256_and_si256(X{j}, mk), _mm256_alignr_epi64(C{j}, {prev}, 3));")+ for j in range(R):+ w(f"\tg |= (uint64_t) _mm256_cmpgt_epu64_mask(X{j}, mk) << {4 * j};")+ w(f"\tp |= (uint64_t) _mm256_cmpeq_epu64_mask(X{j}, mk) << {4 * j};")+ w("\tc = ((g << 1) + p) ^ p;")+ for j in range(R):+ w(f"\tX{j} = _mm256_and_si256(_mm256_mask_add_epi64(X{j}, (__mmask8)(c >> {4 * j} & 15), X{j}, one), mk);")+ w(f"\t_mm256_storeu_si256((__m256i *)(r + {4 * j}), X{j});")+ w("}")+ w("")+ return "\n".join(o)+++def gen_amm(d):+ R = regs(d)+ in_regs = R <= 5+ o = []+ w = o.append+ w(f"/* {d} digits, {R} registers a number */")+ w(f"IFMA_TARGET static void ifma_amm{d}_x2(uint64_t *r1, const uint64_t *a1, const uint64_t *b1,")+ w(f" const uint64_t *m1, uint64_t k1,")+ w(f" uint64_t *r2, const uint64_t *a2, const uint64_t *b2,")+ w(f" const uint64_t *m2, uint64_t k2)")+ w("{")+ w("\tconst __m256i zero = _mm256_setzero_si256();")+ w("#define L(p, k) _mm256_loadu_si256((const __m256i *)((p) + 4 * (k)))")+ X = [f"X{j}" for j in range(R)]+ Y = [f"Y{j}" for j in range(R)]+ w("\t__m256i " + ", ".join(f"{v} = zero" for v in X + Y) + ";")+ if in_regs:+ w("\t__m256i " + ", ".join(f"A{j} = L(a1, {j})" for j in range(R)) + ";")+ w("\t__m256i " + ", ".join(f"B{j} = L(a2, {j})" for j in range(R)) + ";")+ A = [f"A{j}" for j in range(R)]+ B = [f"B{j}" for j in range(R)]+ else:+ A = [f"L(a1, {j})" for j in range(R)]+ B = [f"L(a2, {j})" for j in range(R)]+ M = [f"L(m1, {j})" for j in range(R)]+ N = [f"L(m2, {j})" for j in range(R)]+ w("\tuint64_t x1 = 0, x2 = 0;")+ w("\tint i;")+ w("")+ w(f"\tfor (i = 0; i < {d}; i++) {{")+ w("\t\tuint64_t bi = b1[i], ci = b2[i], y, z;")+ w("\t\t/* lane 0 in full: the products' high halves, which are lane 1's, too */")+ w("\t\tunsigned __int128 s1 = (unsigned __int128) a1[0] * bi + x1;")+ w("\t\tunsigned __int128 s2 = (unsigned __int128) a2[0] * ci + x2;")+ w("\t\t__m256i bv = _mm256_set1_epi64x((long long) bi), cv = _mm256_set1_epi64x((long long) ci);")+ w("\t\t__m256i yv, zv;")+ w("")+ w("\t\ty = ((uint64_t) s1 * k1) & IFMA_MASK52;")+ w("\t\tz = ((uint64_t) s2 * k2) & IFMA_MASK52;")+ w("\t\ts1 += (unsigned __int128) m1[0] * y;")+ w("\t\ts2 += (unsigned __int128) m2[0] * z;")+ w("\t\tyv = _mm256_set1_epi64x((long long) y);")+ w("\t\tzv = _mm256_set1_epi64x((long long) z);")+ for j in range(R):+ w(f"\t\tX{j} = _mm256_madd52lo_epu64(X{j}, {A[j]}, bv); Y{j} = _mm256_madd52lo_epu64(Y{j}, {B[j]}, cv);")+ for j in range(R):+ w(f"\t\tX{j} = _mm256_madd52lo_epu64(X{j}, {M[j]}, yv); Y{j} = _mm256_madd52lo_epu64(Y{j}, {N[j]}, zv);")+ w("\t\t/* down a lane: lane 0 is a multiple of 2^52, and s carries it */")+ for j in range(R):+ nx = f"X{j + 1}" if j + 1 < R else "zero"+ ny = f"Y{j + 1}" if j + 1 < R else "zero"+ w(f"\t\tX{j} = _mm256_alignr_epi64({nx}, X{j}, 1); Y{j} = _mm256_alignr_epi64({ny}, Y{j}, 1);")+ w("\t\tx1 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(X0)) + (uint64_t)(s1 >> 52);")+ w("\t\tx2 = (uint64_t) _mm_cvtsi128_si64(_mm256_castsi256_si128(Y0)) + (uint64_t)(s2 >> 52);")+ for j in range(R):+ w(f"\t\tX{j} = _mm256_madd52hi_epu64(X{j}, {A[j]}, bv); Y{j} = _mm256_madd52hi_epu64(Y{j}, {B[j]}, cv);")+ for j in range(R):+ w(f"\t\tX{j} = _mm256_madd52hi_epu64(X{j}, {M[j]}, yv); Y{j} = _mm256_madd52hi_epu64(Y{j}, {N[j]}, zv);")+ w("\t}")+ w("#undef L")+ w("\t/* lane 0, with the carry it was never given, is what the scalar holds */")+ w("\tX0 = _mm256_mask_set1_epi64(X0, 1, (long long) x1);")+ w("\tY0 = _mm256_mask_set1_epi64(Y0, 1, (long long) x2);")+ w(f"\tifma_norm{R}(r1, " + ", ".join(X) + ");")+ w(f"\tifma_norm{R}(r2, " + ", ".join(Y) + ");")+ w("}")+ w("")+ return "\n".join(o)+++def gen_sel(R):+ o = []+ w = o.append+ w(f"/* both tables' entries k1 and k2 of 32, every entry read and a mask keeping")+ w(f" * one; entries are {4 * R} words apart */")+ w(f"IFMA_TARGET static void ifma_sel{R}(uint64_t *o1, const uint64_t *t1, uint64_t k1,")+ w(f" uint64_t *o2, const uint64_t *t2, uint64_t k2)")+ w("{")+ w("\tconst __m256i one = _mm256_set1_epi64x(1);")+ w("\t__m256i v1 = _mm256_set1_epi64x((long long) k1), v2 = _mm256_set1_epi64x((long long) k2);")+ w("\t__m256i kv = _mm256_setzero_si256();")+ w("\t__m256i " + ", ".join(f"P{j} = kv, Q{j} = kv" for j in range(R)) + ";")+ w("\tint k;")+ w("\tfor (k = 0; k < 32; k++) {")+ w("\t\t__mmask8 s1 = _mm256_cmpeq_epi64_mask(v1, kv), s2 = _mm256_cmpeq_epi64_mask(v2, kv);")+ w(f"\t\tconst uint64_t *e1 = t1 + {4 * R} * k, *e2 = t2 + {4 * R} * k;")+ for j in range(R):+ w(f"\t\tP{j} = _mm256_mask_loadu_epi64(P{j}, s1, e1 + {4 * j}); Q{j} = _mm256_mask_loadu_epi64(Q{j}, s2, e2 + {4 * j});")+ w("\t\tkv = _mm256_add_epi64(kv, one);")+ w("\t}")+ for j in range(R):+ w(f"\t_mm256_storeu_si256((__m256i *)(o1 + {4 * j}), P{j}); _mm256_storeu_si256((__m256i *)(o2 + {4 * j}), Q{j});")+ w("}")+ w("")+ return "\n".join(o)+++def main():+ print(HEADER)+ rs = sorted({regs(d) for d in SIZES})+ for R in rs:+ print(gen_norm(R))+ print(gen_sel(R))+ for d in SIZES:+ print(gen_amm(d))+ print(FOOTER, end="")+++if __name__ == "__main__":+ main()
crypton.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: crypton-version: 2.2.3+version: 2.2.4 -- crypton's own code is BSD-3-Clause. The parts of -- cbits/aes/gcm_fused_x86.c that follow picotls's fusion are MIT, and the -- vendored s2n-bignum assembly in cbits/s2n is taken under ISC, and the@@ -69,7 +69,8 @@ cbits/blake2/ref/*.h cbits/blake2/sse/*.h cbits/crypton_hash_prefix.c- cbits/crypton_mont_sqr.py+ cbits/crypton_mont.py+ cbits/crypton_powm_ifma.py cbits/mlkem/*.S cbits/mlkem/*.c cbits/mlkem/*.h@@ -329,6 +330,7 @@ Crypto.PubKey.Rabin.RW Crypto.PubKey.Rabin.Types Crypto.PubKey.RSA+ Crypto.PubKey.RSA.Blinded Crypto.PubKey.RSA.OAEP Crypto.PubKey.RSA.PKCS15 Crypto.PubKey.RSA.Prim@@ -386,6 +388,7 @@ cbits/crypton_pbkdf2.c cbits/crypton_poly1305.c cbits/crypton_powm.c+ cbits/crypton_powm_ifma.c cbits/crypton_rc4.c cbits/crypton_ripemd.c cbits/crypton_salsa.c@@ -405,6 +408,7 @@ cbits/p256/p256_ec.c other-modules:+ Crypto.PubKey.RSA.Blinded.Internal Crypto.Cipher.AES.Primitive Crypto.Cipher.Blowfish.Primitive Crypto.Cipher.Camellia.Primitive
tests/NumberSpec.hs view
@@ -202,6 +202,13 @@ forAll (wideOf bytes) $ \e -> forAll (wideOf 128) $ \b -> expSafe b e modulus1024 === expFast b e modulus1024+ -- 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+ let ms = [modulus2048 - 2 * 0x10001 * fromIntegral k | k <- [0 .. 11 :: Int]]+ bs = [modulus2048 `div` (3 + fromIntegral k) | k <- [0 .. 11 :: Int]]+ asked = concat (replicate 3 (zip bs ms))+ [(b, m) | (b, m) <- asked, expFast b 65537 m /= expSafe b 65537 m] `shouldBe` [] where safely (b, e, m) = expSafe b e m fastly (b, e, m) = expFast b e m
tests/PubKey/RSASpec.hs view
@@ -7,11 +7,16 @@ module PubKey.RSASpec (spec) where +import Control.Concurrent (forkIO)+import Control.Concurrent.MVar import Crypto.Hash import Crypto.Number.ModArithmetic (inverse) import Crypto.Number.Serialize (i2osp, i2ospOf_, os2ip) import qualified Crypto.PubKey.RSA as RSA+import qualified Crypto.PubKey.RSA.Blinded as RSA+import qualified Crypto.PubKey.RSA.OAEP as OAEP import qualified Crypto.PubKey.RSA.PKCS15 as RSA+import qualified Crypto.PubKey.RSA.PSS as PSS import Crypto.PubKey.RSA.Prim (ep) import qualified Crypto.PubKey.RSA.Prim as Prim import qualified Data.ByteString as B@@ -427,6 +432,110 @@ key = vectorToPrivate vector pub = vectorToPublic vector +-- | A 'RSA.BlindedKey' carries one blinding pair, each operation returning+-- the key with it squared and a new one drawn every 32 uses; the @Safer@+-- functions keep one per key for the last few keys. None of it may change+-- an answer, so every answer is held against the unblinded one, over more+-- uses than one pair lasts.+blindedKeyTests :: Spec+blindedKeyTests = describe "BlindedKey" $ do+ it "signs what signDigest Nothing signs, across refreshes" $+ threaded 100 $ \bk i -> do+ let dg = hashWith SHA256 (B.replicate i 0x61)+ (got, bk') <- RSA.signDigestBlinded bk dg+ got `shouldBe` RSA.signDigest Nothing key dg+ return bk'++ it "signs a DigestInfo as signDigestInfo Nothing does" $+ threaded 40 $ \bk i -> do+ let di = B.replicate (20 + i `mod` 10) (fromIntegral i)+ (got, bk') <- RSA.signDigestInfoBlinded bk di+ got `shouldBe` RSA.signDigestInfo Nothing key di+ return bk'++ it "decrypts what it was given" $+ threaded 40 $ \bk i -> do+ let m = B.replicate i 0x5a+ c <- either (error . show) id <$> RSA.encrypt pub m+ (got, bk') <- RSA.decryptBlinded bk c+ got `shouldBe` (Right m :: Either RSA.Error ByteString)+ return bk'++ it "refuses what decrypt refuses" $ do+ let c = B.replicate (RSA.public_size pub + 1) 1+ (got, _) <- RSA.decryptBlinded (RSA.blindedKey key) c+ got `shouldBe` (Left RSA.MessageSizeIncorrect :: Either RSA.Error ByteString)++ it "makes PSS signatures that verify" $+ threaded 40 $ \bk i -> do+ let m = B.replicate i 0x33+ params = PSS.defaultPSSParams SHA256+ (s, bk') <- PSS.signBlinded params bk m+ either (error . show) (PSS.verify params pub m) s `shouldBe` True+ return bk'++ it "decrypts OAEP" $+ threaded 40 $ \bk i -> do+ let m = B.replicate i 0x77+ params = OAEP.defaultOAEPParams SHA256+ c <- either (error . show) id <$> OAEP.encrypt params pub m+ (got, bk') <- OAEP.decryptBlinded params bk c+ got `shouldBe` Right m+ return bk'++ it "works for a key without its CRT values" $ do+ let bare = key {RSA.private_p = 0, RSA.private_q = 0}+ go _ 41 = return ()+ go bk i = do+ let dg = hashWith SHA256 (B.replicate i 0x62)+ (got, bk') <- RSA.signDigestBlinded bk dg+ got `shouldBe` RSA.signDigest Nothing key dg+ go bk' (i + 1)+ go (RSA.blindedKey bare) (1 :: Int)++ -- The randomness comes from the monad, so a pure generator will do.+ prop "runs in a pure generator" $ \testDRG ->+ let go bk i acc+ | i > (40 :: Int) = return (reverse acc)+ | otherwise = do+ (s, bk') <- RSA.signDigestBlinded bk (hashWith SHA256 (B.replicate i 0x64))+ go bk' (i + 1) (s : acc)+ sigs = withTestDRG testDRG (go (RSA.blindedKey key) 1 [])+ in sigs === [RSA.signDigest Nothing key (hashWith SHA256 (B.replicate i 0x64)) | i <- [1 .. 40]]++ it "gives every thread a right answer through the Safer functions" $ do+ dones <- forM [1 .. 8 :: Int] $ \t -> do+ done <- newEmptyMVar+ _ <- forkIO $ do+ oks <- forM [1 .. 30 :: Int] $ \i -> do+ let dg = hashWith SHA256 (B.pack [fromIntegral t, fromIntegral i])+ got <- RSA.signSaferDigest key dg+ return $! got == RSA.signDigest Nothing key dg+ putMVar done (and oks)+ return done+ results <- mapM takeMVar dones+ results `shouldBe` replicate 8 True++ -- More keys than the Safer functions remember, interleaved, so that the+ -- table both hits and evicts.+ it "keeps the Safer functions right across more keys than it remembers" $ do+ let keys = key : [snd (withTestDRG (TestDRG (s', 2, 3, 4, 5)) (RSA.generate 64 65537)) | s' <- [1 .. 5]]+ forM_ [1 .. 12 :: Int] $ \i ->+ forM_ keys $ \k -> do+ let dg = hashWith SHA256 (B.replicate i 0x63)+ got <- RSA.signSaferDigest k dg+ got `shouldBe` RSA.signDigest Nothing k dg+ where+ vector = firstVector vectorsSHA1+ key = vectorToPrivate vector+ pub = vectorToPublic vector+ -- run count operations, each handed the key the one before returned+ threaded count op = go (RSA.blindedKey key) (1 :: Int)+ where+ go bk i+ | i > count = return ()+ | otherwise = op bk i >>= \bk' -> go bk' (i + 1)+ spec :: Spec spec = do keyGenerationTests@@ -443,5 +552,6 @@ zipWith doMalleabilityTest [katZero ..] $ filter vectorHasSignature vectorsSHA1 digestOperationTests+ blindedKeyTests unpadTests ciphertextRangeTests