diff --git a/IDE/WIN/user_settings.h b/IDE/WIN/user_settings.h index 43c7f3ab3..8152b1def 100644 --- a/IDE/WIN/user_settings.h +++ b/IDE/WIN/user_settings.h @@ -57,11 +57,23 @@ #define WOLFSSL_AESNI #endif - /* Single Precision Support for RSA/DH 1024/2048/3072 and ECC P-256 */ + /* Single Precision Support for RSA/DH 1024/2048/3072 and + * ECC P-256/P-384 */ #define WOLFSSL_SP #define WOLFSSL_HAVE_SP_ECC #define WOLFSSL_HAVE_SP_DH #define WOLFSSL_HAVE_SP_RSA + + #ifdef _WIN64 + /* Old versions of MASM compiler do not recognize newer + * instructions. */ + #if 0 + #define NO_AVX2_SUPPORT + #define NO_MOVBE_SUPPORT + #endif + #define WOLFSSL_SP_ASM + #define WOLFSSL_SP_X86_64_ASM + #endif #endif #else diff --git a/configure.ac b/configure.ac index 1d4e4212f..6bb79ab72 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # @@ -168,6 +168,9 @@ AX_DEBUG AS_IF([test "$ax_enable_debug" = "yes"], [AM_CFLAGS="$DEBUG_CFLAGS $AM_CFLAGS"], [AM_CFLAGS="$AM_CFLAGS -DNDEBUG"]) +AS_IF([test "$ax_enable_debug" = "yes"], + [AM_CCASFLAGS="$DEBUG_CFLAGS $AM_CCASFLAGS"], + [AM_CCASFLAGS="$AM_CCASFLAGS -DNDEBUG"]) # Start without certificates enabled and enable if a certificate algorithm is @@ -449,6 +452,12 @@ then test "$enable_pkcs7" = "" && enable_pkcs7=yes test "$enable_ed25519" = "" && enable_ed25519=yes test "$enable_ed448" = "" && enable_ed448=yes + + if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" + then + test "$enable_eccsi" = "" && enable_eccsi=yes + test "$enable_sakke" = "" && enable_sakke=yes + fi fi # Enable DH const table speedups (eliminates `-lm` math lib dependency) @@ -540,12 +549,18 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT" fi - if test "$ENABLED_FIPS" != "yes" + if test "$ENABLED_FIPS" == "no" then test "$enable_xchacha" = "" && enable_xchacha=yes test "$enable_ed25519" = "" && enable_ed25519=yes test "$enable_ed448" = "" && enable_ed448=yes test "$enable_pkcs7" = "" && enable_pkcs7=yes + + if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" + then + test "$enable_eccsi" = "" && enable_eccsi=yes + test "$enable_sakke" = "" && enable_sakke=yes + fi fi # Enable AES Decrypt, AES ECB, Alt Names, DER Load @@ -2224,6 +2239,36 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT" fi +# Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption (ECCSI) +AC_ARG_ENABLE([eccsi], + [AS_HELP_STRING([--enable-eccsi],[Enable ECCSI (default: disabled)])], + [ ENABLED_ECCSI=$enableval ], + [ ENABLED_ECCSI=no ] + ) + +if test "x$ENABLED_ECCSI" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_ECCSI -DWOLFSSL_PUBLIC_MP" +fi + +# Sakai-Kasahara Key Encryption (SAKKE) - pairing based crypto +AC_ARG_ENABLE([sakke], + [AS_HELP_STRING([--enable-sakke],[Enable SAKKE - paring based crypto (default: disabled)])], + [ ENABLED_SAKKE=$enableval ], + [ ENABLED_SAKKE=no ] + ) + +if test "x$ENABLED_SAKKE" = "xsmall" +then + ENABLED_SAKKE="yes" + ENABLED_SAKKE_SMALL="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_SAKKE_SMALL" +fi +if test "x$ENABLED_SAKKE" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_SAKKE" +fi + # PSK AC_ARG_ENABLE([psk], @@ -4651,6 +4696,11 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_X86_64_BUILD" fi AS_IF([test "x$host_cpu" = "xaarch64"],[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AARCH64_BUILD"]) + + if test "$ENABLED_SAKKE" = "yes" && test "$ENABLED_SAKKE_SMALL" != "yes" + then + AM_CFLAGS="$AM_CFLAGS -funroll-loops -DTFM_SMALL_SET" + fi fi @@ -4944,6 +4994,7 @@ ENABLED_SP_FF_4096=no ENABLED_SP_ECC=no ENABLED_SP_EC_256=no ENABLED_SP_EC_384=no +ENABLED_SP_SAKKE_1024=$ENABLED_SAKKE ENABLED_SP_NO_MALLOC=no ENABLED_SP_NONBLOCK=no ENABLED_SP_SMALL=no @@ -4998,6 +5049,15 @@ do ENABLED_SP_ECC=yes ENABLED_SP_EC_384=yes ;; + smallec1024 | smallp1024 | small1024) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_SAKKE_1024=yes + ;; + ec1024 | p1024 | 1024) + ENABLED_SP_ECC=yes + ENABLED_SP_SAKKE_1024=yes + ;; small2048) ENABLED_SP_SMALL=yes @@ -5116,6 +5176,10 @@ if test "$ENABLED_ECC" != "no" && test "$ENABLED_SP_ECC" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC384 -DWOLFSSL_SP_384" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_384" fi + if test "$ENABLED_SP_SAKKE_1024" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_1024" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_1024" + fi fi if test "$ENABLED_SP_SMALL" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" @@ -6157,6 +6221,8 @@ AM_CONDITIONAL([BUILD_FE448], [test "x$ENABLED_FE448" = "xyes" || test "x$ENABLE AM_CONDITIONAL([BUILD_GE448], [test "x$ENABLED_GE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CURVE448],[test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CURVE448_SMALL],[test "x$ENABLED_CURVE448_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ECCSI],[test "x$ENABLED_ECCSI" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SAKKE],[test "x$ENABLED_SAKKE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_MEMORY],[test "x$ENABLED_MEMORY" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_RSA],[test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_DH],[test "x$ENABLED_DH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) @@ -6483,6 +6549,8 @@ echo " * CURVE448: $ENABLED_CURVE448" echo " * ED448: $ENABLED_ED448" echo " * FPECC: $ENABLED_FPECC" echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" +echo " * ECCSI $ENABLED_ECCSI" +echo " * SAKKE $ENABLED_SAKKE" echo " * ASN: $ENABLED_ASN" echo " * Anonymous cipher: $ENABLED_ANON" echo " * CODING: $ENABLED_CODING" diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index cdb5a2a11..f8ac68330 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -13,6 +13,185 @@ \defgroup ECC Algorithms - ECC \defgroup ED25519 Algorithms - ED25519 \defgroup ED448 Algorithms - ED448 + \defgroup ECCSI_Overview Overview of ECCSI + ECCSI (Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption) is specified in RFC 6507 (https://tools.ietf.org/html/rfc6507). + + In Identity-Based cryptography, there is a Key Management Service that generates keys based on an identity for a client. + The private key (SSK) and public key (PVT) are delivered to the signer and the public key (PVT) only delivered to the verifier on request.\n\n + wolfCrypt offers the ability to: + -# Create KMS keys, + -# Generate signing key pairs, + -# Validate signing key pairs, + -# Sign messages and + -# Verify messages. + + KMS: + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# Make and save or load ECCSI Key: + -# wc_MakeEccsiKey(), wc_ExportEccsiKey(), wc_ExportEccsiPublicKey() or + -# wc_ImportEccsiKey() + -# Wait for request: + -# Receive signing ID from client. + -# Generate signing key pair from ID: wc_MakeEccsiPair() + -# Encode result: + -# For signer, signing key pair: wc_EncodeEccsiPair() + -# Send KPAK and result + -# Free ECCSI Key: wc_FreeEccsiKey() + + Client, signer: + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# (When signing pair not cached) Request KPAK and signing pair from KMS + -# Send signing ID to KMS. + -# Receive signing key pair from KMS. + -# Load KMS Public Key: wc_ImportEccsiPublicKey() + -# Decode signing key pair: wc_DecodeEccsiPair() + -# Validate the key pair: wc_ValidateEccsiPair() + -# (If not done above) Load KMS Public Key: wc_ImportEccsiPublicKey() + -# (If not cached) Calculate hash of the ID and PVT: wc_HashEccsiId() + -# For each message: + -# Set Hash of Identity: wc_SetEccsiHash() + -# Sign message: wc_SignEccsiHash() + -# Send hash ID, message and signature to peer. + -# Free ECCSI Key: wc_FreeEccsiKey() + + Client, verifier: + -# Receive hash ID, message and signature from signer. + -# Request KPAK (if not cached) and PVT (if not cached) for hash ID from KMS. + -# Receive KPAK (if not cached) and PVT (if not cached) for hash ID from KMS. + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# Load KMS Public Key: wc_ImportEccsiPublicKey() + -# Decode PVT: wc_DecodeEccsiPvtFromSig() + -# Calculate hash of the ID and PVT: wc_HashEccsiId() + -# Set ECCSI key pair: wc_SetEccsiPair() + -# Verify signature of message: wc_VerifyEccsiHash() + -# Free ECCSI Key: wc_FreeEccsiKey() + + \defgroup ECCSI_Setup Setup ECCSI Key + Operations for establinshing an ECCSI key. + + Initialize ECCSI Key before use (wc_InitEccsiKey()).\n + Initialize ECCSI Key before use (wc_InitEccsiKey_ex()) for use with a curve other than P256.\n + Either make a new key (wc_MakeEccsiKey()), import an existing key (wc_ImportEccsiKey()) or import existing private key (wc_ImportEccsiPrivateKey()) and public key (wc_ImportEccsiPublicKey()).\n + Export the key (wc_ExportEccsiKey()) after making a new key for future use.\n + Export the private key (wc_ExportEccsiPrivateKey()) after making a new key for future use.\n + Export the public key (wc_ExportEccsiPublicKey()) from KMS to pass to client.\n + Import the public key (wc_ImportEccsiPublicKey()) into client.\n + Free the ECCSI Key (wc_FreeEccsiKey()) when finished. + + \defgroup ECCSI_Operations Operations for Signing and Verifying with ECCSI Key + These operations are for signing and verifying with ECCSI keys. + + Make an ECCSI key pair (wc_MakeEccsiPair()) with the signer's ID for use when signing.\n + Validate the ECCSI key pair (wc_ValidateEccsiPair()) with the signer's ID.\n + Validate the ECCSI Public Validation Token (PVT) (wc_ValidateEccsiPvt()).\n + Encode the ECCSI key pair (wc_EncodeEccsiPair()) for transfer to client.\n + Encode the ECCSI SSK (wc_EncodeEccsiSsk()) for transfer to client.\n + Encode the ECCSI PVT (wc_EncodeEccsiPvt()) for transfer to verifier.\n + Decode the ECCSI key pair (wc_DecodeEccsiPair()) on client for signing.\n + Decode the ECCSI SSK (wc_DecodeEccsiSsk()) on client for signing.\n + Decode the ECCSI PVT (wc_DecodeEccsiPvt()) on client for signing.\n + Decode the ECCSI PVT from the signature (wc_DecodeEccsiPvtFromSig()) on client for verifying.\n + Calculate hash of the ID (wc_HashEccsiId()) for signing/verifying using ID and Public Validation Token (PVT).\n + Sign (wc_SignEccsiHash()) a message with the hash of the ID and the Secret Signing Key (SSK) and Public Validation Token (PVT).\n + Verify (wc_VerifyEccsiHash()) a message with the hash of the signer's ID. + + \defgroup SAKKE_Overview Overview of SAKKE Key + SAKKE (Sakai-Kasahara Key Encryption) is specified in RFC 6508 (https://tools.ietf.org/html/rfc6508). + + SAKKE is used to transfer a secret to a peer using Identity Based cryptography.\n + The Key Management Service (KMS) is responsible for issuing Receiver Secret %Keys (RSKs). + Data up to (2^hashlen)^hashlen bytes of data can be transferred.\n + The sender must know the identity of the receiver and the KMS Public Key.\n + The receiver must have obtained a Receiver Secret Key (RSK) for the identity from a KMS in order to derive the secret. + + KMS: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Make and save or load SAKKE Key: + -# wc_MakeSakkeKey(), wc_ExportSakkeKey(), wc_ExportSakkePublicKey() or + -# wc_ImportSakkeKey() + -# Wait for request: + -# Make an RSK base on ID for the client: wc_MakeSakkeRsk() + -# Encode RSK for transfer to client: wc_EncodeSakkeRsk() + -# Free SAKKE Key: wc_FreeSakkeKey() + + Key Exchange, Peer A: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Generate a random SSV: wc_GenerateSakkeSSV() + -# Set the identity of Peer B: wc_SetSakkeIdentity() + -# Make an encapsulated SSV and auth data: wc_MakeSakkeEncapsulatedSSV() + -# Send encapsulated data to Peer B + -# Free SAKKE Key: wc_FreeSakkeKey() + + Key Exchange, Peer B: + -# Receive encapsulated data. + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Decode RSK transferred from KMS or stored locally: wc_DecodeSakkeRsk() + -# [Optional] Validate RSK before first use: wc_ValidateSakkeRsk() + -# Set the identity: wc_SetSakkeIdentity() + -# Set the RSK and, optionally precomputation table: wc_SetSakkeRsk() + -# Derive SSV with auth data: wc_DeriveSakkeSSV() + -# Free SAKKE Key: wc_FreeSakkeKey() + + Transfer secret, Peer A: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Set the identity of Peer B: wc_SetSakkeIdentity() + -# Make an encapsulation of the SSV and auth data: wc_MakeSakkeEncapsulatedSSV() + -# Send encapsulated data to Peer B + -# Free SAKKE Key: wc_FreeSakkeKey() + + Transfer secret, Peer B: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Decode RSK transferred from KMS or stored locally: wc_DecodeSakkeRsk() + -# [Optional] Validate RSK before first use: wc_ValidateSakkeRsk() + -# Receive encapsulated data. + -# Set the identity: wc_SetSakkeIdentity() + -# Set the RSK and, optionally precomputation table: wc_SetSakkeRsk() + -# Derive SSV and auth data: wc_DeriveSakkeSSV() + -# Free SAKKE Key: wc_FreeSakkeKey() + + \defgroup SAKKE_Setup Setup SAKKE Key + Operations for establishing a SAKKE key. + + Initialization SAKKE Key before use (wc_InitSakkeKey() or wc_InitSakkeKey_ex()).\n + Either make a new key (wc_MakeSakkeKey()) or import an existing key (wc_ImportSakkeKey()).\n + Export the key (wc_ExportSakkeKey()) after making a new key for future use.\n + If only the private part of the KMS SAKKE Key is available, make the public key (wc_MakeSakkePublicKey()).\n + Export the private key (wc_ExportSakkePrivateKey()) from KMS from storage.\n + Import the private key (wc_ImportSakkePrivateKey()) into KMS from storage.\n + Export the public key (wc_ExportSakkePublicKey()) from KMS to pass to client.\n + Import the public key (wc_ImportSakkePublicKey()) into client.\n + Set the identity to use (wc_SetSakkeIdentity()) into client.\n + Free the SAKKE Key (wc_FreeSakkeKey()) when finished. + + \defgroup SAKKE_RSK Operations on/with SAKKE RSK + These operations make, validate, encode and decode a Receiver Secret Key (RSK). + + An RSK is required to derive an SSV (see wc_DeriveSakkeSSV()).\n + On the KMS, make an RSK (wc_MakeSakkeRsk()) from the client's ID.\n + On the client, validate the RSK (wc_ValidateSakkeRsk()) with the ID.\n + Encode the RSK (wc_EncodeSakkeRsk()) to pass to client or for storage.\n + Decode the RSK (wc_DecodeSakkeRsk()) on the client when needed.\n + Import the RSK (wc_ImportSakkeRsk()) on the client when needed.\n + Set the RSK and, optionally, a pre-computation table (wc_SetSakkeRsk()) on the client when needed. + + \defgroup SAKKE_Operations Operations using SAKKE Key + These operations transfer a Shared Secret Value (SSV) from one client to another. The SSV may be randomly generated. + + Calculate the size of the authentication data (wc_GetSakkeAuthSize()) to determine where the SSV starts in a buffer.\n + Make the intermediate point I (wc_MakeSakkePointI()) to speed making an encapsulated and deriving SSV.\n + Get intermediate point I (wc_GetSakkePointI()) for storage.\n + Set intermediate point I (wc_SetSakkePointI()) from storage.\n + Generate a pre-computation table for intermediate point I (wc_GenerateSakkePointITable()) to further enhance performance. Store as necessary.\n + Set the pre-computation table for intermediate point I (wc_SetSakkePointITable()) to further enhance performance.\n + Clear the pre-computation table for intermediate point I (wc_ClearSakkePointITable()) to remove reference to external table pointer.\n + Make an encapsulated SSV (wc_MakeSakkeEncapsulatedSSV()) to share with another client. Data in SSV is modified.\n + Generate a random SSV (wc_GenerateSakkeSSV()) for key exchange.\n + Derive the SSV, (wc_DeriveSakkeSSV()) on the recipient from the encapsulated SSV. + \defgroup HC128 Algorithms - HC-128 \defgroup HMAC Algorithms - HMAC \defgroup IDEA Algorithms - IDEA diff --git a/doc/dox_comments/header_files/doxygen_pages.h b/doc/dox_comments/header_files/doxygen_pages.h index 015c73a3f..262236297 100644 --- a/doc/dox_comments/header_files/doxygen_pages.h +++ b/doc/dox_comments/header_files/doxygen_pages.h @@ -39,6 +39,8 @@
. + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [out] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_pairing(const SakkeKey* key, const ecc_point* p, + const ecc_point* q, mp_int* r, const byte* table, word32 len) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + if (table == NULL) { + err = sp_Pairing_1024(p, q, r); + } + else { + err = sp_Pairing_precomp_1024(p, q, r, table, len); + } + } +#else + (void)key; + (void)p; + (void)q; + (void)r; + (void)table; + (void)len; +#endif + + return err; +} + +#else /* WOLFSSL_HAVE_SP_ECC */ +/** + * Generate a pre-computation table for the RSK point. + * + * Empty table as not supported in this implementation. + * + * @param [in] key SAKKE key. + * @param [in] rsk Point to generate table for. + * @param [out] table Pre-generated values. Passing NULL indicates that + * the length of the table is required. + * @param [in,out] len On in, the size of table buffer in bytes. + * On out, the size of the pre-generated data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rsk or len is NULL. + * @return LENGTH_ONLY_E when table is NULL. + * @return BAD_LENGTH_E when table is specified and len is too small. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_GenerateSakkeRskTable(const SakkeKey* key, const ecc_point* rsk, + byte* table, word32* len) +{ + int err = 0; + + if ((key == NULL) || (rsk == NULL) || (len == 0)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)table; + + return err; +} + +/* + * Square a modulo m in Montgomery. + * + * @param [in] a MP integer that is number to square. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_mont_sqrmod(mp_int* a, mp_int* m, mp_int* r, mp_digit mp) +{ + int err; + + err = mp_sqr(a, r); + if (err == 0) { + err = mp_montgomery_reduce(r, m, mp); + } + + return err; +} + +/* + * Multiply a by b modulo m in Montgomery. + * + * @param [in] a MP integer that is first number to multiply. + * @param [in] b MP integer that is second number to multiply. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_mont_mulmod(mp_int* a, mp_int* b, mp_int* m, mp_int* r, + mp_digit mp) +{ + int err; + + err = mp_mul(a, b, r); + if (err == 0) { + err = mp_montgomery_reduce(r, m, mp); + } + + return err; +} + +/* + * Add a and b modulo m. r = a + b % m + * + * @param [in] a MP integer that is first number to add. + * @param [in] b MP integer that is second number to add. + * @param [out] m MP integer that is modulus. + * @param [in] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_addmod(mp_int* a, mp_int* b, mp_int* m, mp_int* r) +{ + int err; + + err = mp_add(a, b, r); + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + + return err; +} + +/* + * Triple a modulo m. r = 3.a % m + * + * @param [in] a MP integer that is number to triple + * @param [out] m MP integer that is modulus. + * @param [in] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_tplmod(mp_int* a, mp_int* m, mp_int* r) +{ + int err; + + err = mp_mul_d(a, 3, r); + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + + return err; +} + +/* + * Subtract b from a modulo m. r = a - b % m + * + * @param [in] a MP integer that is first number to add. + * @param [in] b MP integer that is second number to add. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_submod(mp_int* a, mp_int* b, mp_int* m, mp_int* r) +{ + int err; + +#if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE) + err = mp_sub(a, b, r); + if ((err == 0) && mp_isneg(r)) { + err = mp_add(r, m, r); + } +#else + err = sp_submod_ct(a, b, m, r); +#endif + + return err; +} + +/* + * Square the element of PF_p[q] (projectivization of F_p with order q). + * + * Calculation: + * r.x = (p.x + p.y) * (p.x - p.y) + * r.y = (p.x * p.y) * 2 + * + * @param [in] p MP projective integer - value to square. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - Result of square. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_sqr(mp_proj* p, mp_int* prime, mp_digit mp, mp_proj* r, + mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x + p.y */ + err = sakke_addmod(p->x, p->y, prime, t1); + /* t2 = p.x - p.y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, t2); + } + /* r.y = p.x * p.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, p->y, prime, r->y, mp); + } + /* r.x = (p.x + p.y) * (p.x - p.y) */ + if (err == 0) { + err = sakke_mont_mulmod(t1, t2, prime, r->x, mp); + } + /* r.y = (p.x * p.y) * 2 */ + if (err == 0) { + err = sakke_addmod(r->y, r->y, prime, r->y); + } + + return err; +} + +/* + * Multiply two elements of PF_p[q] (projectivization of F_p with order q). + * + * q must not be the same object as r. + * Calculation: + * r.x = (p.x * q.x) - (p.y * q.y) + * r.y = (p.x * q.y) + (p.y * q.x) + * + * @param [in] p MP projective integer - first value to multiply. + * @param [in] q MP projective integer - second value to multiply. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Result of operation. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_mul(mp_proj* p, mp_proj* q, mp_int* prime, mp_digit mp, + mp_proj* r, mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x * q.y */ + err = sakke_mont_mulmod(p->x, q->y, prime, t1, mp); + /* r->x = p.x * q.x */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, q->x, prime, r->x, mp); + } + /* t2 = p.y * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q->y, prime, t2, mp); + } + /* r.x = (p.x * q.x) - (p.y * q.y) */ + if (err == 0) { + err = sakke_submod(r->x, t2, prime, r->x); + } + /* r.y = p.y * q.x */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q->x, prime, r->y, mp); + } + /* r.y = (p.x * q.y) + (p.y * q.x) */ + if (err == 0) { + err = sakke_addmod(t1, r->y, prime, r->y); + } + + return err; +} + +/* + * Multiply two elements of PF_p[q] (projectivization of F_p with order q). + * + * q must not be the same object as r. + * Calculation: + * r.x = (p.x * q.x) - (p.y * q.y) + * r.y = (p.x * q.y) + (p.y * q.x) + * But qx = 1 + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * @param [in] p MP projective integer - first value to multiply. + * @param [in] q MP projective integer - second value to multiply. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Result of operation. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_mul_qx1(mp_proj* p, mp_int* q, mp_int* prime, mp_digit mp, + mp_proj* r, mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x * q.y */ + err = sakke_mont_mulmod(p->x, q, prime, t1, mp); + /* t2 = p.y * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q, prime, t2, mp); + } + /* r.x = p.x - (p.y * q.y) */ + if (err == 0) { + err = sakke_submod(p->x, t2, prime, r->x); + } + /* r.y = (p.x * q.y) + p.y */ + if (err == 0) { + err = sakke_addmod(t1, p->y, prime, r->y); + } + + return err; +} + +/* + * Calculate the gradient of line through P, P and [-2]P. + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] t2 MP integer temporary. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] l MP integer representing gradient. + * @param [out] z2 MP integer representing p.z^2. + */ +static int sakke_calc_dbl_rx(ecc_point* p, ecc_point* q, mp_int* prime, + mp_digit mp, mp_proj* r, mp_int* l, mp_int* z2) +{ + int err; + mp_int* t = r->y; + + /* z2 = p.z^2 */ + err = sakke_mont_sqrmod(p->z, prime, z2, mp); + /* t = p.x + p.z^2 */ + if (err == 0) { + err = sakke_addmod(p->x, z2, prime, l); + } + /* r1 = p.x - p.z^2 */ + if (err == 0) { + err = sakke_submod(p->x, z2, prime, t); + } + /* l = ((p.x - p.z^2) * (p.x + p.z^2) = p.x ^ 2 - p.z^4 */ + if (err == 0) { + err = sakke_mont_mulmod(l, t, prime, l, mp); + } + /* l = ((p.x ^ 2) - p.z^4) * 3 */ + if (err == 0) { + err = sakke_tplmod(l, prime, l); + } + /* t = q.x * p.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, z2, prime, t, mp); + } + /* t = p.x + q.x * p.z^2 */ + if (err == 0) { + err = sakke_addmod(p->x, t, prime, t); + } + /* r.x = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_mont_mulmod(l, t, prime, r->x, mp); + } + + return err; +} + +#ifdef WOLFSSL_SAKKE_SMALL +/* + * Calculate gradient of line through P, P and [-2]P and accumulate line. + * + * Calculation: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y + * v* = v*^2 * r* + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] q ECC point - second point on the elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - gradient in PF_p[q]. + * @param [in] t1 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_dbl(mp_proj* v, ecc_point* p, ecc_point* q, + mp_int* prime, mp_digit mp, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = r->z; + mp_int* z2 = t[1]; + mp_int* l = t1; + + /* v = v^2 */ + err = sakke_proj_sqr(v, prime, mp, v, t1, t2); + /* l = 3 * (p.x^2 - p.z^4), z2 = p.z^2, rx = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_calc_dbl_rx(p, q, prime, mp, r, l, z2); + } + /* t1 = p.y ^ 2 */ + if (err == 0) { + err = sakke_mont_sqrmod(p->y, prime, t1, mp); + } + /* t1 = 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_addmod(t1, t1, prime, t1); + } + /* r.x -= 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* r.y = p.y * 2 */ + if (err == 0) { + err = sakke_addmod(p->y, p->y, prime, r->y); + } + /* r.y = (p.y * 2) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* t2 = p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(p->z, z2, prime, t2, mp); + } + /* r.y *= p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, t2, prime, r->y, mp); + } + /* v = v^2 * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + return err; +} + +/* + * Calculate gradient of line through C, P and -C-P and accumulate line. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * + * @param [in] p First point on elliptic curve. + * @param [in] q Second point on elliptic curve. + * @param [in] c Third point on elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Resulting gradient in PF_p[q]. + * @param [in] t MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_add_one(mp_proj* v, mp_int* prime, mp_digit mp, + ecc_point* p, ecc_point* q, ecc_point* c, mp_proj* r, mp_int* t1) +{ + int err; + mp_int* t2 = r->z; + + /* r.x = (q.x + p.x) * c.y */ + err = sakke_addmod(q->x, p->x, prime, r->x); + if (err == 0) { + err = sakke_mont_mulmod(r->x, c->y, prime, r->x, mp); + } + /* t2 = c.z^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(c->z, prime, t2, mp); + } + /* t = q.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, t2, prime, t1, mp); + } + /* t = q.x * c.z^2 + c.x */ + if (err == 0) { + err = sakke_addmod(t1, c->x, prime, t1); + } + /* t = (q.x * c.z^2 + c.x) * p.y */ + if (err == 0) { + err = sakke_mont_mulmod(t1, p->y, prime, t1, mp); + } + /* t *= c.z */ + if (err == 0) { + err = sakke_mont_mulmod(t1, c->z, prime, t1, mp); + } + /* r.x -= t */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* t = p.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, t2, prime, t1, mp); + } + /* r.y = c.x - p.x * c.z^2 */ + if (err == 0) { + err = sakke_submod(c->x, t1, prime, r->y); + } + /* r.y = (c.x - p.x) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* r.y = c.x - p.x) * q.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, c->z, prime, r->y, mp); + } + /* v = v * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + return err; +} +#else +/* + * Calculate gradient of line through P, P and [-2]P and accumulate line. + * Double the point p. + * + * Calculation: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] q ECC point - second point on the elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - gradient in PF_p[q]. + * @param [in] t1 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_dbl(mp_proj* v, ecc_point* p, ecc_point* q, + mp_int* prime, mp_digit mp, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = r->z; + mp_int* z2 = t[1]; + mp_int tmp[2]; + mp_int* l = &tmp[0]; + mp_int* ty = &tmp[1]; + + err = mp_init(l); + if (err == 0) { + err = mp_init(ty); + } + + /* v = v^2 */ + if (err == 0) { + err = sakke_proj_sqr(v, prime, mp, v, t1, t2); + } + /* l = 3 * (p.x^2 - p.z^4), z2 = p.z^2, rx = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_calc_dbl_rx(p, q, prime, mp, r, l, z2); + } + /* ty = p.y ^ 2 */ + if (err == 0) { + err = sakke_mont_sqrmod(p->y, prime, ty, mp); + } + /* ty = 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_addmod(ty, ty, prime, ty); + } + /* r.x -= 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_submod(r->x, ty, prime, r->x); + } + /* r.y = p.y * 2 */ + if (err == 0) { + err = sakke_addmod(p->y, p->y, prime, r->y); + } + /* r.y = p.y * 2 * p.z */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, p->z, prime, p->z, mp); + } + /* r.y = p.y * 2 * p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(p->z, z2, prime, r->y, mp); + } + /* r.y = (p.y * 2 * p.z^3) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* v = v^2 * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + /* Double point using previously calculated values + * l = 3 * (X - Z^2).(X + Z^2) + * ty = 2 * Y^2 + * Z = 2 * Y * Z + */ + /* Y = 2 * 2 * Y^2 */ + if (err == 0) { + err = sakke_addmod(ty, ty, prime, p->y); + } + /* T2 = 4 * Y^4 */ + if (err == 0) { + err = sakke_mont_sqrmod(ty, prime, t2, mp); + } + /* T2 = 8 * Y^4 */ + if (err == 0) { + err = sakke_addmod(t2, t2, prime, t2); + } + /* Y = Y * X */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, p->x, prime, p->y, mp); + } + /* X = l * l */ + if (err == 0) { + err = sakke_mont_sqrmod(l, prime, p->x, mp); + } + /* X = X - Y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, p->x); + } + /* X = X - Y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, p->x); + } + /* Y = Y - X */ + if (err == 0) { + err = sakke_submod(p->y, p->x, prime, p->y); + } + /* Y = Y * l */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, l, prime, p->y, mp); + } + /* Y = Y - T2 */ + if (err == 0) { + err = sakke_submod(p->y, t2, prime, p->y); + } + + mp_free(ty); + mp_free(l); + + return err; +} + +/* + * Calculate gradient of line through C, P and -C-P and accumulate line. + * Add point p into c. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in] p First point on elliptic curve. + * @param [in] q Second point on elliptic curve. + * @param [in] c Third point on elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Resulting gradient in PF_p[q]. + * @param [in] t MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_add_one(mp_proj* v, mp_int* prime, mp_digit mp, + ecc_point* p, ecc_point* q, ecc_point* c, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = t[1]; + mp_int tmp[4]; + mp_int* h = &tmp[0]; + mp_int* ty = &tmp[1]; + mp_int* tz = &tmp[2]; + mp_int* t3 = &tmp[3]; + + err = mp_init_multi(h, ty, tz, t3, NULL, NULL); + + /* r.x = (q.x + p.x) * c.y */ + if (err == 0) { + err = sakke_addmod(q->x, p->x, prime, r->x); + } + if (err == 0) { + err = sakke_mont_mulmod(r->x, c->y, prime, r->x, mp); + } + /* tz = c.z^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(c->z, prime, tz, mp); + } + /* t = q.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, tz, prime, t1, mp); + } + /* t = q.x * c.z^2 + c.x */ + if (err == 0) { + err = sakke_addmod(t1, c->x, prime, t1); + } + /* ty = p.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, c->z, prime, ty, mp); + } + /* t = (q.x * c.z^2 + c.x) * p.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(t1, ty, prime, t1, mp); + } + /* r.x -= t */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* t = p.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, tz, prime, t1, mp); + } + /* h = c.x - p.x * c.z^2 */ + if (err == 0) { + err = sakke_submod(c->x, t1, prime, h); + } + /* t3 = (c.x - p.x * c.z^2 ) * c.z*/ + if (err == 0) { + err = sakke_mont_mulmod(h, c->z, prime, t3, mp); + } + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(t3, q->y, prime, r->y, mp); + } + /* v = v * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * ty = p.y * c.z + * tz = c.z^2 + * t3 = (c.x - p.x * c.z^2) * c.z + */ + + /* R = p.y * c.z^3 - c.y */ + if (err == 0) { + err = sakke_mont_mulmod(ty, tz, prime, ty, mp); + } + if (err == 0) { + err = sakke_submod(ty, c->y, prime, ty); + } + /* c'.z = -H * c.z */ + if (err == 0) { + err = sakke_submod(prime, t3, prime, c->z); + } + /* c'.x = R^2 + H^3 - 2 * c.x * H^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(ty, prime, t1, mp); + } + if (err == 0) { + err = sakke_mont_sqrmod(h, prime, t2, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(c->x, t2, prime, t3, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(t2, h, prime, t2, mp); + } + if (err == 0) { + err = sakke_addmod(t1, t2, prime, c->x); + } + if (err == 0) { + err = sakke_addmod(t3, t3, prime, t1); + } + if (err == 0) { + err = sakke_submod(c->x, t1, prime, c->x); + } + /* c'.y = R * (c.x * H^2 - c'.x) + c.y * H^3 */ + if (err == 0) { + err = sakke_submod(t3, c->x, prime, t3); + } + if (err == 0) { + err = sakke_mont_mulmod(t3, ty, prime, t3, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(t2, c->y, prime, t2, mp); + } + if (err == 0) { + err = sakke_addmod(t3, t2, prime, c->y); + } + + mp_free(t3); + mp_free(tz); + mp_free(ty); + mp_free(h); + + return err; +} +#endif /* WOLFSSL_SAKKE_SMALL */ + +/* + * Calculate r = pairing
.
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [out] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_pairing(SakkeKey* key, ecc_point* p, ecc_point* q, mp_int* r,
+ const byte* table, word32 len)
+{
+ int err;
+ ecc_point* v = key->params.base;
+ ecc_point* c = key->tmp.p1;
+ mp_proj* t2 = key->tmp.p3;
+ mp_int* t3 = &key->tmp.m2;
+ mp_int* prime = &key->params.prime;
+ mp_int* t[] = { &key->tmp.m1, t3 };
+ int i;
+ mp_digit mp = 0;
+ SakkeKeyParams* params = &key->params;
+
+ (void)table;
+ (void)len;
+
+ err = sakke_point_to_mont(p, prime, &key->tmp.m1, 0);
+ if (err == 0) {
+ err = sakke_point_to_mont(q, prime, &key->tmp.m1, 1);
+ }
+ if (err == 0) {
+ err = wc_ecc_copy_point(p, c);
+ }
+ /* Set v to 1. */
+ if (err == 0) {
+ params->haveBase = 0;
+ err = mp_set(v->x, 1);
+ }
+ if (err == 0) {
+ err = mp_set(v->y, 0);
+ }
+ if (err == 0) {
+ err = mp_montgomery_setup(prime, &mp);
+ }
+
+ for (i = mp_count_bits(¶ms->q) - 2; (err == 0) && (i >= 0); i--) {
+#ifdef WOLFSSL_SAKKE_SMALL
+ /* Accumulate line into v and double point. */
+ err = sakke_accumulate_line_dbl(v, c, q, prime, mp, t2, t);
+ if (err == 0) {
+ err = ecc_projective_dbl_point(c, c, NULL, prime, mp);
+ }
+
+ if ((err == 0) && (i > 0) && mp_is_bit_set(¶ms->q, i)) {
+ /* Accumulate line into v and add P into C. */
+ err = sakke_accumulate_line_add_one(v, prime, mp, p, q, c, t2,
+ &key->tmp.m1);
+ if (err == 0) {
+ err = ecc_projective_add_point(p, c, c, NULL, prime, mp);
+ }
+ }
+#else
+ /* Accumulate line into v and double point. */
+ err = sakke_accumulate_line_dbl(v, c, q, prime, mp, t2, t);
+
+ if ((err == 0) && (i > 0) && mp_is_bit_set(¶ms->q, i)) {
+ /* Accumulate line into v and add P into C. */
+ err = sakke_accumulate_line_add_one(v, prime, mp, p, q, c, t2, t);
+ }
+#endif /* WOLFSSL_SAKKE_SMALL */
+ }
+
+ /* Final exponentiation */
+ if (err == 0) {
+ err = sakke_proj_sqr(v, prime, mp, v, &key->tmp.m1, t3);
+ }
+ if (err == 0) {
+ err = sakke_proj_sqr(v, prime, mp, v, &key->tmp.m1, t3);
+ }
+ /* Convert from PF_p[q] to F_p */
+ if (err == 0) {
+ err = mp_invmod(v->x, prime, r);
+ }
+ if (err == 0) {
+ err = mp_mulmod(r, v->y, prime, r);
+ }
+
+ if (err == 0) {
+ err = sakke_point_from_mont(p, prime, mp);
+ }
+ if (err == 0) {
+ err = sakke_point_from_mont(q, prime, mp);
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+/**
+ * Set the Receiver Secret Key (RSK) and any table associated with it.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] rsk Receiver Secret Key (RSK) as an ECC point.
+ * @param [in] table Pre-computation table. May be NULL.
+ * @param [in] len Size of pre-compuration table in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or rsk is NULL.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int wc_SetSakkeRsk(SakkeKey* key, const ecc_point* rsk, byte* table, word32 len)
+{
+ int err = 0;
+
+ if ((key == NULL) || (rsk == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+ if (err == 0) {
+ key->rsk.set = 0;
+ err = wc_ecc_copy_point(rsk, key->rsk.rsk);
+ }
+ if (err == 0) {
+ key->rsk.table = table;
+ key->rsk.tableLen = len;
+ key->rsk.set = 1;
+ }
+
+ return err;
+}
+
+/*
+ * Compute the elliptic curve point I for device B. Partial for point R.
+ *
+ * RFC 6508, Section 6.2.1, Step 3.\n
+ * RFC 6508, Section 6.2.2, Step 5.\n
+ * I = [b]P + Z_S
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] id Identifier to of device B.
+ * @param [in] idSz Size of identifier in bytes.
+ * @param [out] i ECC point - partial for point R.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_compute_point_i(SakkeKey* key, const byte* id, word16 idSz,
+ ecc_point* i)
+{
+ int err;
+ mp_int* b = &key->ecc.k;
+
+ /* Load b - ID of receiver */
+ err = mp_read_unsigned_bin(b, id, idSz);
+ if (err == 0) {
+ err = sakke_load_base_point(key);
+ }
+#ifndef WOLFSSL_HAVE_SP_ECC
+ /* Convert to montgomery form for add operation. */
+ if (err == 0) {
+ err = sakke_z_to_mont(key, &key->tmp.m2);
+ }
+#endif
+ /* [b]P + Z_S */
+ if (err == 0) {
+ ecc_point* z = &key->ecc.pubkey;
+ err = sakke_mulmod_base_add(key, b, z, i, 1);
+ }
+ return err;
+}
+
+/**
+ * Validate the Receiver Secret Key (RSK) with the identity.
+ *
+ * RFC 6508, Section 6.1.2
+ *
+ * A receiving client should validate an RSK before use.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] id Identity to use.
+ * @param [in] idSz Size of identity in bytes.
+ * @param [in] rsk Receiver Secret Key as an ECC point.
+ * @param [out] valid 1 indicates RSK is valid for identity.
+ * 0 otherwise.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key, id, rsk or valid is NULL.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_ValidateSakkeRsk(SakkeKey* key, const byte* id, word16 idSz,
+ ecc_point* rsk, int* valid)
+{
+ int err = 0;
+ mp_int* a = NULL;
+
+ if ((key == NULL) || (id == NULL) || (rsk == NULL) || (valid == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ /* Load elliptic curve parameters */
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ err = sakke_load_base_point(key);
+ }
+ /* Load pairing base - g */
+ if (err == 0) {
+ err = sakke_load_pairing_base(key);
+ }
+ /* Load a - identifier */
+ if (err == 0) {
+ a = &key->tmp.m1;
+ err = mp_read_unsigned_bin(a, id, idSz);
+ }
+
+ if (err == 0) {
+ /* I = [b]P + Z_S */
+ err = sakke_compute_point_i(key, id, idSz, key->i.i);
+ if ((err == 0) && (idSz <= SAKKE_ID_MAX_SIZE)) {
+ XMEMCPY(key->i.id, id, idSz);
+ key->i.idSz = idSz;
+ }
+ }
+ /* < [a]P + Z, K_(a,T) > = < K_(a,T), [a]P + Z > = < rsk, i >*/
+ if (err == 0) {
+ err = sakke_pairing(key, rsk, key->i.i, a, NULL, 0);
+ }
+
+ /* Compare pairing result with generator. */
+ if (valid != NULL) {
+ *valid = ((err == 0) && (mp_cmp(a, &key->params.g) == MP_EQ));
+ }
+
+ return err;
+}
+
+/**
+ * Get the size of the authentication data that is the first part of the
+ * encapsulated data.
+ *
+ * Clients need to know how long the authentication data so as the SSV starts
+ * after the authentication data in a buffer.\n
+ * For SAKKE parameter set 1: 257 bytes
+ *
+ * @param [in] key SAKKE key.
+ * @param [out] authSz Size of authentication data in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or authSz is NULL.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_GetSakkeAuthSize(SakkeKey* key, word16* authSz)
+{
+ int err = 0;
+
+ if ((key == NULL) || (authSz == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ word16 n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8);
+ *authSz = 1 + 2 * n;
+ }
+
+ return err;
+}
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+/*
+ * Modular exponentiate the value in F_p*.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] b MP integer that is the base to exponentiate.
+ * @param [in] e MP integer that is the exponent.
+ * @param [out] r Result of exponentiation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_modexp(const SakkeKey* key, const mp_int* b, mp_int* e,
+ mp_int* r)
+{
+ int err = NOT_COMPILED_IN;
+
+#ifdef WOLFSSL_SP_1024
+ if ((key->ecc.idx != ECC_CUSTOM_IDX) &&
+ (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) {
+ err = sp_ModExp_Fp_star_1024(b, e, r);
+ }
+#endif
+
+ return err;
+}
+#else
+#ifdef WOLFSSL_SAKKE_SMALL
+/*
+ * Modular exponentiate the value in F_p*.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] b MP integer that is the base to exponentiate.
+ * @param [in] e MP integer that is the exponent.
+ * @param [out] c Result of exponentiation.
+ * @param [in] mp Multiplier to use when converting from Montgomery form.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_modexp_loop(SakkeKey* key, mp_int* b, mp_int* e, mp_proj* c,
+ mp_digit mp)
+{
+ int err;
+ mp_int* t1 = &key->tmp.m1;
+ mp_int* t2 = &key->tmp.m2;
+ mp_int* by = key->tmp.p1->z;
+ mp_int* prime = &key->params.prime;
+ int i;
+
+ /* Set the working value to the base in PF_p[q] */
+ err = mp_montgomery_calc_normalization(c->x, prime);
+ /* Set c->y as montgomery form of b - base */
+ if (err == 0) {
+ err = mp_mulmod(b, c->x, prime, by);
+ }
+ /* Set by as montgomery form of b - base */
+ if (err == 0) {
+ err = mp_copy(by, c->y);
+ }
+ /* Simple non-constant time exponentiation over a field. */
+ for (i = mp_count_bits(e) - 2; (err == 0) && (i >= 0); i--) {
+ err = sakke_proj_sqr(c, prime, mp, c, t1, t2);
+ if (err == 0) {
+ if (mp_is_bit_set(e, i)) {
+ err = sakke_proj_mul_qx1(c, by, prime, mp, c, t1, t2);
+ }
+ }
+ }
+
+ return err;
+}
+
+#elif defined(WOLFSSL_SAKKE_SMALL_MODEXP) || !defined(USE_FAST_MATH)
+
+/*
+ * Modular exponentiate the value in F_p*.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] b MP integer that is the base to exponentiate.
+ * @param [in] e MP integer that is the exponent.
+ * @param [out] r Result of exponentiation.
+ * @param [in] mp Multiplier to use when converting from Montgomery form.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_modexp_loop(SakkeKey* key, mp_int* b, mp_int* e, mp_proj* r,
+ mp_digit mp)
+{
+ int err;
+#ifdef WC_NO_CACHE_RESISTANT
+ mp_proj* c[2] = { r, key->tmp.p2 };
+#else
+ mp_proj* c[3] = { r, key->tmp.p3, key->tmp.p2 };
+#endif
+ mp_int* t1 = &key->tmp.m1;
+ mp_int* t2 = &key->tmp.m2;
+ mp_int* by = key->tmp.p1->z;
+ mp_int* prime = &key->params.prime;
+ int i;
+
+ /* Set the working value to the base in PF_p[q] */
+ err = mp_montgomery_calc_normalization(c[0]->x, prime);
+ /* Set c[0] to [mont_one, zero] */
+ if (err == 0) {
+ mp_zero(c[0]->y);
+ }
+ /* Set by is montgomery form of b - base */
+ if (err == 0) {
+ err = mp_mulmod(b, c[0]->x, prime, by);
+ }
+ for (i = mp_count_bits(&key->params.q) - 1; (err == 0) && (i >= 0); i--) {
+ int j = mp_is_bit_set(e, i);
+ err = sakke_proj_sqr(c[0], prime, mp, c[0], t1, t2);
+ if (err == 0) {
+#ifdef WC_NO_CACHE_RESISTANT
+ err = sakke_proj_mul_qx1(c[0], by, prime, mp, c[j^1], t1, t2);
+#else
+ err = sakke_proj_mul_qx1(c[0], by, prime, mp, c[2], t1, t2);
+ mp_copy(c[2]->x,
+ (mp_int*) ( ((wolfssl_word)c[0]->x & wc_off_on_addr[j]) +
+ ((wolfssl_word)c[1]->x & wc_off_on_addr[j^1]) ) );
+ mp_copy(c[2]->y,
+ (mp_int*) ( ((wolfssl_word)c[0]->y & wc_off_on_addr[j]) +
+ ((wolfssl_word)c[1]->y & wc_off_on_addr[j^1]) ) );
+#endif
+ }
+ }
+
+ return err;
+}
+
+#else
+
+/* Table for 8-bit striping exponentiation. */
+static const byte sakke_1024_g_table[256][128] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x59, 0xe9, 0x3c, 0x6a, 0x6b, 0xd3, 0xba, 0xf4, 0xaf, 0xd5,
+ 0x88, 0x91, 0xe8, 0x6c, 0xb2, 0x21, 0x61, 0x52, 0xba, 0x02,
+ 0xc7, 0x27, 0xc9, 0x8e, 0x21, 0xf1, 0x1c, 0x06, 0x7d, 0x3b,
+ 0x4f, 0x7d, 0x66, 0xdb, 0xd0, 0x9a, 0x9b, 0x67, 0xe0, 0x96,
+ 0x6f, 0xaf, 0x7a, 0x00, 0x61, 0xc1, 0xf3, 0x0d, 0x0e, 0x74,
+ 0x1a, 0x1b, 0x2d, 0x8e, 0xae, 0x58, 0xd6, 0xd8, 0x59, 0xbf,
+ 0x16, 0xac, 0x6c, 0x6f, 0xad, 0xde, 0xdc, 0x85, 0x8f, 0x88,
+ 0x71, 0x7c, 0x27, 0xbe, 0x88, 0x2c, 0x2f, 0xd1, 0x51, 0xe6,
+ 0xd8, 0x9e, 0x2d, 0x14, 0x72, 0xbf, 0x1a, 0xfb, 0x3a, 0xf4,
+ 0x9b, 0xb4, 0xb3, 0x65, 0x76, 0xd1, 0x26, 0x46, 0xf8, 0x15,
+ 0x82, 0x64, 0x24, 0x75, 0x40, 0xe8, 0xf3, 0xdf, 0x43, 0xca,
+ 0x4a, 0x73, 0xea, 0xc9, 0xe9, 0x71, 0xe1, 0x00, 0x7a, 0x58,
+ 0x17, 0x0a, 0x46, 0xd2, 0x33, 0x5c, 0x16, 0x85 },
+ { 0x63, 0xef, 0x18, 0x7b, 0x74, 0xf6, 0x2e, 0x03, 0xbe, 0x85,
+ 0xac, 0x6a, 0x9b, 0x6a, 0x52, 0xb9, 0x5f, 0x19, 0xc2, 0x0d,
+ 0x6f, 0x83, 0x73, 0xd3, 0x16, 0xf1, 0x86, 0x31, 0x50, 0xa9,
+ 0xd0, 0xd9, 0x13, 0x94, 0x6d, 0x17, 0x9f, 0x7b, 0xfa, 0x2e,
+ 0xdd, 0x9f, 0x6a, 0x91, 0x0a, 0x18, 0x0e, 0xb6, 0x51, 0xf7,
+ 0x11, 0x9b, 0x4a, 0xc8, 0x43, 0x1c, 0xfd, 0x45, 0x62, 0x67,
+ 0x40, 0x38, 0x98, 0x13, 0x81, 0x3d, 0x1c, 0xb2, 0x2e, 0xcb,
+ 0x96, 0x52, 0xb9, 0xbd, 0x3a, 0xfd, 0xf5, 0xcb, 0x6a, 0xb5,
+ 0x11, 0x8b, 0xd7, 0x92, 0xc1, 0x13, 0x99, 0xfa, 0x97, 0x53,
+ 0x79, 0x4c, 0x8f, 0x5c, 0x14, 0x18, 0x85, 0x88, 0xaa, 0x99,
+ 0x3f, 0x52, 0x09, 0x28, 0x9e, 0xa5, 0xa4, 0x4e, 0xa1, 0x9f,
+ 0x65, 0x30, 0xbb, 0xc9, 0xcc, 0x9f, 0x00, 0xae, 0xf1, 0xe6,
+ 0xe5, 0x4d, 0xd3, 0x6f, 0x71, 0xdd, 0x45, 0x94 },
+ { 0x4f, 0xe6, 0x79, 0x1c, 0xf1, 0x92, 0xda, 0x23, 0x90, 0xdc,
+ 0xc7, 0x94, 0xdd, 0xac, 0x2c, 0xda, 0x50, 0x5e, 0x8e, 0xc2,
+ 0xeb, 0x19, 0x96, 0x33, 0x68, 0x2e, 0xcc, 0x49, 0x47, 0x68,
+ 0x5f, 0xbe, 0xab, 0x0c, 0xb6, 0x3c, 0x12, 0x9f, 0x85, 0xcb,
+ 0xb1, 0x36, 0x09, 0x86, 0x15, 0x55, 0x9c, 0x41, 0x7f, 0xf3,
+ 0x35, 0x4e, 0x3f, 0x98, 0x60, 0xc8, 0xa0, 0xed, 0x29, 0x9b,
+ 0x0f, 0x5c, 0x6c, 0xd1, 0xae, 0x18, 0x28, 0x30, 0x73, 0x3f,
+ 0xa3, 0xbe, 0x93, 0x3e, 0x0d, 0x41, 0xb3, 0x30, 0xbc, 0x4d,
+ 0x5b, 0x40, 0x74, 0x74, 0xbb, 0x60, 0xf8, 0xcf, 0xbd, 0xa4,
+ 0x1b, 0x1f, 0x72, 0x41, 0x09, 0x8b, 0x6f, 0xdb, 0xf0, 0xa2,
+ 0xc7, 0xaf, 0xd8, 0x1d, 0x73, 0x92, 0xf7, 0x41, 0xce, 0x42,
+ 0x9b, 0x60, 0x1c, 0x1b, 0xdb, 0x57, 0x2b, 0xec, 0x82, 0xf8,
+ 0x7c, 0x37, 0x6b, 0x7f, 0x01, 0x6f, 0x45, 0xe7 },
+ { 0x04, 0x48, 0x2a, 0x18, 0x56, 0x1d, 0xb2, 0x97, 0x55, 0x5d,
+ 0x1f, 0xfe, 0xbe, 0x78, 0xd9, 0xd2, 0x18, 0xc2, 0x1f, 0x61,
+ 0x1a, 0x04, 0x01, 0x70, 0x30, 0x95, 0x70, 0xc4, 0x4e, 0x9a,
+ 0x1e, 0x52, 0xfa, 0x4d, 0xb1, 0x14, 0x8e, 0x95, 0x07, 0x61,
+ 0x30, 0xcf, 0xa7, 0xce, 0x5c, 0xac, 0x4a, 0xab, 0xb5, 0x5e,
+ 0xfd, 0xd0, 0x60, 0x68, 0x9a, 0x9a, 0xea, 0x52, 0xd0, 0x26,
+ 0x23, 0x3f, 0x98, 0xd5, 0xaa, 0xa7, 0xa6, 0x1a, 0x7b, 0x81,
+ 0xce, 0xa6, 0x43, 0x0a, 0x6d, 0xe5, 0xe8, 0x8c, 0xea, 0xf6,
+ 0x9d, 0xfd, 0xe9, 0xed, 0xb2, 0xc1, 0x7b, 0x09, 0x00, 0xc8,
+ 0x75, 0xe2, 0x71, 0x3b, 0xd7, 0x21, 0x0c, 0x44, 0x71, 0xc6,
+ 0xdb, 0x41, 0x81, 0xcc, 0x23, 0x7c, 0x7e, 0x88, 0xe9, 0x61,
+ 0xb3, 0x22, 0xcc, 0x84, 0x5e, 0x65, 0x1d, 0x57, 0x17, 0xc1,
+ 0x94, 0xa4, 0x23, 0xd5, 0x05, 0xe8, 0x73, 0x3c },
+ { 0x83, 0x3a, 0x0f, 0xf8, 0xde, 0xdb, 0xf8, 0x9f, 0x1a, 0x9c,
+ 0x3f, 0x25, 0x68, 0xcc, 0xdb, 0x44, 0xfa, 0x13, 0x50, 0xd3,
+ 0xe7, 0x34, 0x27, 0x02, 0x0d, 0x26, 0x7f, 0xd9, 0x86, 0x92,
+ 0x07, 0x7a, 0x66, 0xe1, 0xa4, 0x9f, 0xd7, 0x35, 0x57, 0xe9,
+ 0x5b, 0x51, 0x85, 0x4d, 0x35, 0x45, 0x96, 0x68, 0x40, 0xc2,
+ 0x7a, 0x04, 0x32, 0xa3, 0xd2, 0x22, 0x96, 0x3b, 0x05, 0x3e,
+ 0xd7, 0xb2, 0xea, 0x45, 0xc8, 0xe4, 0x49, 0x9c, 0x57, 0x12,
+ 0x8d, 0x37, 0xd6, 0xf2, 0x1f, 0x1a, 0x7e, 0x44, 0xfe, 0xb5,
+ 0x28, 0xfc, 0x30, 0x7c, 0x45, 0x31, 0xbc, 0x60, 0x56, 0x0b,
+ 0xee, 0x25, 0xbd, 0x8c, 0x22, 0x60, 0xa0, 0xe5, 0x4f, 0x02,
+ 0xf3, 0x37, 0x36, 0x30, 0x72, 0x3c, 0x99, 0xfc, 0x21, 0x88,
+ 0xab, 0x4f, 0x81, 0x69, 0xf9, 0x46, 0x61, 0xcd, 0xc1, 0xe7,
+ 0xe7, 0x75, 0x8a, 0xc2, 0x73, 0xd4, 0x86, 0xd8 },
+ { 0x69, 0x2b, 0x3c, 0xe3, 0xeb, 0x24, 0x96, 0x5f, 0x2e, 0x2d,
+ 0xf9, 0x5a, 0x85, 0xf8, 0x11, 0xa0, 0x74, 0x1f, 0xd5, 0x1a,
+ 0xf4, 0xf0, 0x5c, 0x0c, 0x03, 0xf7, 0x3e, 0xa6, 0xa2, 0xb7,
+ 0x44, 0xf1, 0x1f, 0xec, 0x95, 0xe1, 0xd8, 0xa1, 0x05, 0x8a,
+ 0x22, 0xd6, 0x39, 0xc8, 0xcb, 0x11, 0x87, 0xdb, 0x42, 0x13,
+ 0xbe, 0x88, 0x2d, 0xd0, 0x6e, 0xc0, 0xf3, 0x66, 0xed, 0x59,
+ 0xe9, 0xdb, 0xad, 0xd1, 0x33, 0x9e, 0xda, 0xd6, 0xa1, 0xd5,
+ 0xc2, 0x70, 0xe5, 0x13, 0x35, 0x0b, 0xe6, 0xeb, 0x26, 0x0b,
+ 0x04, 0xbe, 0x5a, 0xee, 0xb4, 0xc1, 0x6a, 0x2a, 0x56, 0xfe,
+ 0xe0, 0x7b, 0x09, 0x8c, 0x0a, 0x88, 0x93, 0x1b, 0xa5, 0x1e,
+ 0xa6, 0x25, 0x75, 0xa6, 0xe5, 0x6b, 0xb9, 0xe2, 0xa9, 0x0c,
+ 0x51, 0x4d, 0x3b, 0x72, 0x94, 0xf3, 0x27, 0xd0, 0xf0, 0xcc,
+ 0xa8, 0xc4, 0x19, 0xc7, 0xab, 0x37, 0x6b, 0x76 },
+ { 0x33, 0x3e, 0x43, 0x0a, 0xf4, 0x00, 0x42, 0xd6, 0xc0, 0xcf,
+ 0x0a, 0xaf, 0x81, 0xde, 0x5f, 0xe0, 0x77, 0x41, 0x91, 0xb1,
+ 0x89, 0xef, 0x09, 0xf2, 0x64, 0x47, 0x90, 0x38, 0x70, 0x36,
+ 0x1f, 0x25, 0x32, 0xd6, 0x43, 0x31, 0xd4, 0x12, 0x83, 0x27,
+ 0x8c, 0x4e, 0x85, 0x33, 0x54, 0x52, 0x64, 0x3c, 0x05, 0xb9,
+ 0x49, 0x1c, 0xa0, 0x9d, 0x46, 0x95, 0x58, 0x1f, 0xa3, 0x97,
+ 0x3d, 0x65, 0x29, 0x36, 0x54, 0xc2, 0x40, 0xd7, 0x7d, 0x2a,
+ 0xf8, 0x31, 0x17, 0x4d, 0x0b, 0x40, 0x74, 0xe2, 0x52, 0xf9,
+ 0x2f, 0x42, 0x6c, 0xae, 0x4d, 0xe4, 0xe6, 0x65, 0xc8, 0x14,
+ 0x5c, 0x6d, 0xb2, 0xed, 0xbe, 0x8c, 0x16, 0x3d, 0x9a, 0x01,
+ 0xe0, 0xab, 0x96, 0xee, 0x43, 0xec, 0xf4, 0x63, 0x47, 0xa3,
+ 0x76, 0x16, 0x66, 0xa4, 0x6e, 0xa5, 0x8f, 0x92, 0x81, 0x6f,
+ 0x0c, 0xe6, 0xcb, 0x72, 0xd2, 0xa1, 0x27, 0xb4 },
+ { 0x10, 0xe8, 0xb3, 0x1d, 0xd6, 0xbb, 0xd7, 0x08, 0xae, 0x12,
+ 0x76, 0x36, 0x2f, 0x77, 0x91, 0xd1, 0xbb, 0x18, 0xd1, 0x75,
+ 0x4a, 0xeb, 0x02, 0xa3, 0x8a, 0xdc, 0x6f, 0xe5, 0x45, 0x9e,
+ 0xa4, 0x62, 0xeb, 0x9a, 0x71, 0xa1, 0x15, 0xaa, 0xa4, 0x08,
+ 0x94, 0xfe, 0x18, 0x62, 0x65, 0x72, 0xcd, 0x52, 0xb3, 0xa1,
+ 0x04, 0xe5, 0xcd, 0xde, 0xb5, 0x8c, 0x3f, 0xc2, 0x1e, 0x74,
+ 0x04, 0x63, 0x13, 0x86, 0xb5, 0x44, 0x34, 0x83, 0xfe, 0x3e,
+ 0xe7, 0x55, 0x94, 0x8a, 0x37, 0xaf, 0xf1, 0x3b, 0x85, 0x87,
+ 0xd9, 0xd0, 0x4d, 0xd9, 0x65, 0xc9, 0x13, 0xbb, 0x1f, 0xfc,
+ 0x9d, 0x7d, 0x0b, 0x06, 0x10, 0x37, 0xef, 0x29, 0x1e, 0xa4,
+ 0x85, 0x03, 0x73, 0x60, 0xa4, 0x01, 0x3c, 0x5f, 0x18, 0x08,
+ 0xb6, 0x64, 0x57, 0xa7, 0x73, 0x06, 0xb5, 0x3f, 0x79, 0xbe,
+ 0x5d, 0xf0, 0x4d, 0xe4, 0xcf, 0x26, 0xd3, 0xb7 },
+ { 0x64, 0x85, 0x52, 0x4c, 0x0c, 0xdc, 0xc4, 0xbc, 0xfd, 0x26,
+ 0x1c, 0x83, 0x2a, 0x84, 0x95, 0xab, 0x38, 0x64, 0x6b, 0x32,
+ 0xe7, 0xac, 0x0a, 0x06, 0x9a, 0x87, 0x39, 0x3f, 0x5b, 0x6f,
+ 0x55, 0x57, 0x3c, 0x8e, 0x1d, 0xb2, 0xda, 0x0a, 0x55, 0x68,
+ 0xcb, 0x1f, 0xbc, 0x54, 0xf3, 0x5e, 0x1a, 0x88, 0xcf, 0xcb,
+ 0x6e, 0xae, 0x4f, 0xdc, 0x3f, 0x7f, 0xfe, 0x59, 0x0d, 0xfe,
+ 0x03, 0x6c, 0x03, 0x57, 0x90, 0x38, 0xf9, 0x5d, 0x2f, 0xbe,
+ 0xb5, 0x4c, 0x6d, 0xc7, 0xfc, 0x7c, 0x26, 0xd5, 0x5e, 0xf5,
+ 0x97, 0x82, 0xe9, 0xe4, 0x93, 0x82, 0x54, 0x7a, 0xb1, 0x65,
+ 0x4d, 0x17, 0x1a, 0xf9, 0x9c, 0x15, 0x18, 0x77, 0xe2, 0xb0,
+ 0x26, 0xb1, 0xe8, 0x5b, 0x38, 0xdc, 0xd6, 0x30, 0x74, 0xce,
+ 0x15, 0xb8, 0x03, 0xad, 0x24, 0x77, 0x56, 0x67, 0x61, 0x66,
+ 0xb8, 0x7f, 0x03, 0xe5, 0x3e, 0xd9, 0xf1, 0xaf },
+ { 0x1f, 0x76, 0xf3, 0xf2, 0xf2, 0x34, 0x56, 0x3c, 0xa4, 0x06,
+ 0x1c, 0x7a, 0x2d, 0xf8, 0xb4, 0x49, 0x65, 0x46, 0xa6, 0x0c,
+ 0x00, 0xa3, 0x3d, 0x80, 0x24, 0x07, 0x8b, 0xac, 0xfa, 0x38,
+ 0x3f, 0x09, 0xa6, 0x50, 0xa8, 0xf5, 0x63, 0x2d, 0x28, 0xb2,
+ 0x32, 0x75, 0x8d, 0x24, 0x57, 0x4b, 0x99, 0x97, 0x13, 0x5c,
+ 0x44, 0x37, 0x19, 0x81, 0x18, 0x2d, 0x5d, 0x51, 0x81, 0xd5,
+ 0xb9, 0x14, 0xbe, 0x7c, 0x70, 0x0b, 0x19, 0x03, 0x57, 0x0c,
+ 0xbb, 0x5b, 0x92, 0x41, 0x1f, 0xeb, 0x91, 0x7b, 0x1e, 0x7a,
+ 0xb9, 0xf0, 0x76, 0x4d, 0x49, 0xa0, 0x1f, 0x05, 0x38, 0x18,
+ 0x6a, 0xe9, 0xd2, 0xa1, 0x82, 0xcb, 0x23, 0x37, 0x88, 0x3a,
+ 0xba, 0x5d, 0xbd, 0x93, 0x88, 0x42, 0x27, 0xf0, 0x89, 0xaf,
+ 0xf7, 0x42, 0x2a, 0xa0, 0x3f, 0xba, 0x35, 0xa6, 0x42, 0x8a,
+ 0x1a, 0xbf, 0xb3, 0xe2, 0xc4, 0xa6, 0xff, 0x2a },
+ { 0x04, 0x92, 0x4f, 0xfb, 0x3d, 0x10, 0x8e, 0x05, 0xd0, 0xf3,
+ 0x67, 0xbb, 0x04, 0x9e, 0xa7, 0x26, 0xc0, 0x28, 0xca, 0x94,
+ 0x4e, 0xd2, 0xa5, 0x38, 0xfd, 0x9f, 0xc3, 0x3c, 0x04, 0xed,
+ 0x89, 0x9d, 0x3c, 0x25, 0x62, 0xaf, 0xf1, 0xd4, 0x99, 0x5a,
+ 0xaf, 0x92, 0xa4, 0xcc, 0xdc, 0x84, 0xbc, 0x92, 0x3a, 0x6f,
+ 0x93, 0xdd, 0x18, 0x12, 0xac, 0xb7, 0x7f, 0x87, 0x80, 0x26,
+ 0x2e, 0xe5, 0xfd, 0xe8, 0xa9, 0x8a, 0x5a, 0x8c, 0x9b, 0xb9,
+ 0x44, 0x3a, 0xb2, 0x7b, 0xf6, 0x93, 0x11, 0x6b, 0x74, 0x88,
+ 0xa9, 0x9f, 0x29, 0x15, 0x3a, 0xdc, 0xe7, 0x1e, 0xf8, 0x31,
+ 0x46, 0x4f, 0x7d, 0x0a, 0xfa, 0x48, 0x85, 0x76, 0x1f, 0x41,
+ 0xed, 0x56, 0xba, 0x82, 0x35, 0xf3, 0x11, 0x7b, 0x5f, 0x6d,
+ 0xb2, 0xdf, 0x79, 0x07, 0x05, 0x56, 0x1f, 0x69, 0xc8, 0x7a,
+ 0x9a, 0xa2, 0xc1, 0x43, 0x44, 0xc4, 0x36, 0xb0 },
+ { 0x4d, 0xfc, 0xe8, 0x09, 0xc3, 0x80, 0xae, 0x35, 0x08, 0xcd,
+ 0x84, 0x9c, 0xc1, 0x46, 0x84, 0x26, 0x58, 0xa8, 0x2b, 0x76,
+ 0x9f, 0x14, 0x27, 0x99, 0x87, 0x80, 0xa7, 0x84, 0xf3, 0xc5,
+ 0x3b, 0xce, 0xda, 0xd9, 0xe1, 0x82, 0x90, 0x62, 0xfa, 0x49,
+ 0xb4, 0x0b, 0x07, 0x2e, 0x25, 0x07, 0x26, 0x61, 0x79, 0xa7,
+ 0xb2, 0xcb, 0x15, 0x08, 0x27, 0x2a, 0xc9, 0x7e, 0x24, 0xa3,
+ 0x92, 0x5e, 0x5f, 0x4e, 0xf8, 0xa0, 0xdf, 0x66, 0xe0, 0x12,
+ 0x90, 0xd3, 0x4a, 0xe8, 0xb7, 0xd4, 0x20, 0x99, 0x1b, 0x8c,
+ 0x4b, 0x8e, 0xbb, 0x8e, 0x14, 0xd7, 0xe9, 0x5b, 0x76, 0x73,
+ 0x91, 0xc0, 0x41, 0xd6, 0xe1, 0x8e, 0x42, 0x4e, 0x20, 0x64,
+ 0x6e, 0xbe, 0x55, 0x7b, 0xe6, 0x1f, 0xd3, 0x2b, 0x5e, 0x1c,
+ 0x69, 0x77, 0xd3, 0xb3, 0x30, 0x25, 0xe2, 0xea, 0xe4, 0x8c,
+ 0x06, 0x54, 0x8e, 0x3d, 0xc6, 0x73, 0x56, 0x2f },
+ { 0x0d, 0x07, 0x59, 0x08, 0xb8, 0xa0, 0x68, 0x02, 0xdc, 0x7d,
+ 0xaf, 0xf8, 0x93, 0x39, 0xbd, 0x23, 0xc5, 0x62, 0x59, 0x5d,
+ 0xe4, 0x28, 0xa4, 0x08, 0x59, 0xe9, 0xe8, 0x1d, 0xe2, 0x15,
+ 0x3c, 0x22, 0x24, 0xa5, 0x71, 0x53, 0x9f, 0x3a, 0x53, 0x2f,
+ 0x30, 0x7f, 0xd7, 0xd8, 0x47, 0xd0, 0x12, 0x28, 0x7f, 0xce,
+ 0xcb, 0x04, 0x5c, 0x4e, 0xd9, 0xba, 0xf1, 0x73, 0xdc, 0x2e,
+ 0x81, 0xdc, 0x56, 0xb3, 0x1e, 0x10, 0xf1, 0x39, 0xd1, 0x5c,
+ 0x8d, 0x8a, 0x83, 0xfa, 0x8c, 0xc5, 0xca, 0x91, 0x6e, 0x7c,
+ 0xd6, 0x89, 0x13, 0x82, 0x45, 0xf0, 0xff, 0x47, 0x4c, 0x65,
+ 0x26, 0x23, 0x55, 0x4a, 0xdf, 0x3c, 0x34, 0x10, 0x2c, 0x26,
+ 0xbb, 0x2d, 0x1b, 0x2b, 0x10, 0xcc, 0x60, 0x0b, 0xe2, 0x7d,
+ 0x02, 0x63, 0xd5, 0x2d, 0xa0, 0x15, 0x97, 0x79, 0x30, 0xdd,
+ 0x45, 0x06, 0x9c, 0xb2, 0xd5, 0x27, 0xb7, 0x80 },
+ { 0x24, 0xfa, 0x96, 0x1c, 0x2f, 0x08, 0x53, 0x5a, 0xf2, 0xcd,
+ 0xe2, 0x15, 0xa4, 0x36, 0x0d, 0xfe, 0xfb, 0xee, 0xd7, 0xed,
+ 0x70, 0x0c, 0x11, 0x51, 0x28, 0x3f, 0x74, 0x4d, 0x39, 0x3f,
+ 0x2e, 0x2a, 0xb6, 0x86, 0x12, 0xb9, 0xf0, 0x49, 0x28, 0xe9,
+ 0xf5, 0xda, 0xfc, 0xec, 0x52, 0x61, 0x17, 0xe5, 0xef, 0x0d,
+ 0x22, 0x44, 0x1c, 0xfc, 0xbc, 0x52, 0x88, 0x3d, 0x0b, 0xb5,
+ 0xa8, 0xd6, 0x4e, 0xf6, 0x39, 0x2f, 0x28, 0x96, 0x27, 0x26,
+ 0x95, 0xbe, 0x01, 0x48, 0xcf, 0x1c, 0x79, 0x10, 0xc6, 0x82,
+ 0x5c, 0x05, 0xc2, 0xf5, 0x6d, 0xca, 0x36, 0x15, 0x83, 0xb9,
+ 0x60, 0x21, 0xf6, 0x22, 0xda, 0x0d, 0x1f, 0x02, 0xa2, 0xe4,
+ 0x85, 0x59, 0xf8, 0x51, 0x88, 0xc0, 0xd2, 0x61, 0x59, 0xca,
+ 0x41, 0x3b, 0x88, 0xfc, 0xd2, 0x4f, 0xbe, 0x99, 0xb2, 0xe5,
+ 0x87, 0x0a, 0xf2, 0xa7, 0xde, 0x08, 0x5f, 0x2a },
+ { 0x37, 0x1c, 0xc2, 0x3d, 0xfc, 0x4f, 0x01, 0x14, 0x94, 0xd7,
+ 0xa0, 0x3d, 0x4a, 0x6f, 0xb6, 0xe1, 0x20, 0x1f, 0x61, 0xd1,
+ 0x77, 0x52, 0xfa, 0x60, 0x8e, 0xff, 0x77, 0xe3, 0x75, 0x56,
+ 0x03, 0xf3, 0xf6, 0x35, 0xb1, 0xfc, 0x8f, 0x4d, 0x7d, 0x4e,
+ 0x5e, 0x1b, 0x8b, 0x7f, 0xe5, 0x0e, 0xe1, 0x73, 0x8c, 0xeb,
+ 0x75, 0x9f, 0x39, 0xad, 0x43, 0xab, 0x27, 0x3e, 0x1c, 0x8f,
+ 0x41, 0x95, 0x01, 0x58, 0xc0, 0x32, 0x14, 0xe9, 0xcc, 0x94,
+ 0x2f, 0x9e, 0x5a, 0x57, 0xf4, 0x86, 0xc9, 0x89, 0x51, 0x45,
+ 0xba, 0xb4, 0x6a, 0xf4, 0xd6, 0xc2, 0x7d, 0x12, 0x18, 0xb1,
+ 0x91, 0xdf, 0xcc, 0x89, 0xa0, 0x60, 0x22, 0x84, 0xf3, 0x45,
+ 0x68, 0x96, 0x43, 0xdb, 0x17, 0x4d, 0xaa, 0x90, 0x6e, 0x82,
+ 0xd5, 0x44, 0x64, 0x30, 0x57, 0xd8, 0xfb, 0xd9, 0x03, 0x26,
+ 0x07, 0x67, 0xdb, 0x3f, 0x61, 0x6d, 0xf7, 0xf6 },
+ { 0x92, 0xb6, 0xbc, 0xa0, 0x0c, 0x80, 0xfb, 0x7f, 0x3e, 0x60,
+ 0x2e, 0x4f, 0xc9, 0xf4, 0xd7, 0x8f, 0x33, 0x0f, 0x6a, 0x7a,
+ 0xf1, 0xbc, 0x13, 0xe8, 0x03, 0xc2, 0xc0, 0xe8, 0x5b, 0xa6,
+ 0xe6, 0xc6, 0x06, 0xf6, 0xa5, 0x8d, 0x76, 0x40, 0xc3, 0x0e,
+ 0x70, 0xd9, 0x7d, 0x07, 0x26, 0xdd, 0xe2, 0x4a, 0x45, 0x69,
+ 0x7e, 0x91, 0xe8, 0x7d, 0x34, 0x74, 0x40, 0xa4, 0x94, 0xd3,
+ 0x3a, 0x80, 0x20, 0x38, 0x3f, 0x9a, 0x6d, 0x78, 0x99, 0xcb,
+ 0x39, 0x53, 0x12, 0x80, 0xf1, 0x56, 0xe0, 0x02, 0x40, 0xf2,
+ 0x88, 0x36, 0xcd, 0x08, 0xdc, 0x4c, 0x80, 0x7b, 0xdc, 0x4f,
+ 0x7e, 0x36, 0x08, 0x10, 0x01, 0x27, 0xcc, 0x28, 0xc1, 0x64,
+ 0x6f, 0x57, 0x64, 0x2f, 0x77, 0xa8, 0x92, 0x02, 0xf6, 0x50,
+ 0xb3, 0x1b, 0x6d, 0x19, 0x6e, 0xbf, 0x36, 0x4d, 0x9c, 0x06,
+ 0x28, 0x9b, 0x11, 0x5d, 0xda, 0x90, 0xc3, 0x51 },
+ { 0x71, 0xff, 0x62, 0xc9, 0x4f, 0x02, 0xf8, 0x9d, 0xe7, 0xdb,
+ 0x4b, 0x98, 0xcf, 0x33, 0x87, 0x1c, 0x21, 0x5a, 0xd8, 0x30,
+ 0x1f, 0x27, 0x7e, 0x31, 0x9a, 0xaf, 0x6e, 0x67, 0x79, 0x0e,
+ 0x30, 0x88, 0xd7, 0xec, 0x5e, 0xda, 0xa3, 0xb6, 0x27, 0x59,
+ 0xf4, 0x01, 0x41, 0xb8, 0x3f, 0xd5, 0x8f, 0x65, 0xfe, 0x2b,
+ 0xae, 0x08, 0x4a, 0x9b, 0x63, 0xb6, 0xa4, 0xe1, 0xd8, 0x72,
+ 0x5c, 0xde, 0xbb, 0x70, 0xe8, 0xf0, 0x9e, 0x7e, 0x00, 0xf0,
+ 0xc0, 0xf9, 0xcd, 0x47, 0x2a, 0xfa, 0xea, 0x3b, 0x91, 0x53,
+ 0xed, 0xfb, 0x7b, 0xaa, 0x4a, 0x92, 0xca, 0x27, 0x0b, 0xee,
+ 0x9c, 0xee, 0x1b, 0xb1, 0x41, 0x3f, 0x6b, 0x4e, 0x32, 0xad,
+ 0xa7, 0xcc, 0x19, 0x54, 0x81, 0xc3, 0x29, 0xc4, 0x92, 0xb0,
+ 0xa3, 0x30, 0x0e, 0x82, 0x57, 0x12, 0xb8, 0xb1, 0x6f, 0x12,
+ 0x2e, 0x3d, 0x5c, 0x83, 0x5f, 0x00, 0x82, 0x2e },
+ { 0x40, 0xfd, 0x47, 0xe7, 0x5f, 0x95, 0x82, 0x73, 0xe6, 0xa8,
+ 0x3f, 0xe9, 0xdf, 0x1b, 0xba, 0x69, 0x6c, 0x18, 0xb3, 0x50,
+ 0x84, 0xef, 0x6b, 0x4c, 0xf1, 0xe1, 0x9f, 0xc6, 0xfd, 0xc3,
+ 0x7d, 0xda, 0x38, 0xdb, 0xb6, 0x3e, 0xa3, 0xd2, 0x66, 0x1c,
+ 0xd3, 0xaa, 0x0f, 0x7d, 0xd2, 0x22, 0x64, 0x32, 0xed, 0xde,
+ 0x69, 0x2a, 0x72, 0xcc, 0xd1, 0xf0, 0x92, 0xed, 0xc4, 0xb1,
+ 0xb6, 0xd4, 0xf6, 0x8a, 0x75, 0x3f, 0x28, 0xa0, 0x33, 0xaf,
+ 0x53, 0x6b, 0x8b, 0x83, 0x2d, 0x46, 0xf5, 0x98, 0x28, 0xc1,
+ 0xe1, 0xe9, 0xf9, 0x90, 0xca, 0x04, 0x41, 0x80, 0xa4, 0xc5,
+ 0x98, 0xe1, 0x09, 0xe6, 0x50, 0x33, 0x83, 0xf5, 0xef, 0x9f,
+ 0xff, 0xf1, 0x20, 0xa5, 0x3b, 0x11, 0xa8, 0xa5, 0xf1, 0xcd,
+ 0x65, 0x78, 0xe2, 0xee, 0x4a, 0xcd, 0x5e, 0xbc, 0x71, 0xe6,
+ 0xaa, 0x4c, 0x71, 0x02, 0x2a, 0x4a, 0x84, 0xd9 },
+ { 0x5b, 0x1c, 0x11, 0x57, 0xe6, 0x39, 0x33, 0x8c, 0x0b, 0x33,
+ 0x4d, 0x98, 0xdf, 0xfb, 0xe2, 0x86, 0x68, 0xd8, 0x21, 0x11,
+ 0xd8, 0x54, 0xa6, 0x95, 0x18, 0xb9, 0xfa, 0xb3, 0xf9, 0xb6,
+ 0xae, 0x43, 0x1a, 0xc1, 0x6a, 0x26, 0x1f, 0x57, 0x8a, 0xa3,
+ 0x20, 0xcf, 0x0b, 0x97, 0xf7, 0x30, 0x08, 0x4d, 0xe5, 0x2c,
+ 0x01, 0x39, 0xec, 0x6c, 0x21, 0x74, 0x14, 0xd6, 0x8a, 0x08,
+ 0x41, 0x13, 0x42, 0x5c, 0x2d, 0x85, 0xd4, 0x52, 0x1b, 0x46,
+ 0x83, 0x37, 0x93, 0x38, 0x9c, 0x05, 0x41, 0x71, 0xfb, 0x69,
+ 0x95, 0xd5, 0xc9, 0x6e, 0xb5, 0xa2, 0x19, 0x50, 0xcf, 0xc2,
+ 0x21, 0x4a, 0x8a, 0xc8, 0xff, 0x88, 0x69, 0xbe, 0xeb, 0xa1,
+ 0x2e, 0xb6, 0xef, 0xc2, 0xdd, 0x9e, 0xc8, 0x8e, 0x69, 0x86,
+ 0x25, 0x48, 0x6d, 0xbb, 0xfc, 0x1e, 0xea, 0xb6, 0xf2, 0xfb,
+ 0x5b, 0x88, 0xb7, 0x46, 0x26, 0x71, 0x40, 0xa4 },
+ { 0x96, 0x3a, 0xb8, 0x3a, 0xa7, 0x56, 0xee, 0xf4, 0x84, 0xde,
+ 0x9c, 0xb8, 0x33, 0xe5, 0x0a, 0xb3, 0xce, 0x16, 0x48, 0x01,
+ 0x6e, 0x1c, 0x63, 0x44, 0xe4, 0xd3, 0xfc, 0x44, 0xda, 0x0f,
+ 0xd5, 0x91, 0xb6, 0xad, 0x1c, 0xf4, 0x78, 0x5e, 0x67, 0xa3,
+ 0x0a, 0xc3, 0xbd, 0x66, 0xc7, 0x79, 0x1a, 0x48, 0x1f, 0x91,
+ 0x65, 0x1c, 0x7d, 0xa1, 0x2c, 0x10, 0x4f, 0xd1, 0xac, 0xe6,
+ 0x81, 0xc6, 0x5f, 0x57, 0xab, 0x18, 0xd8, 0x30, 0xea, 0x6e,
+ 0xdc, 0xa8, 0x28, 0x09, 0xc7, 0x64, 0xa4, 0xf3, 0x2c, 0x9d,
+ 0x16, 0xe7, 0x06, 0xe7, 0x05, 0x6d, 0xcf, 0x94, 0xcb, 0x2d,
+ 0x66, 0xa3, 0x63, 0x24, 0x20, 0xdc, 0x31, 0x6d, 0xc6, 0x5f,
+ 0xcb, 0x54, 0xdc, 0xe4, 0xf4, 0x2b, 0xa3, 0xc5, 0xfe, 0x69,
+ 0x4c, 0x73, 0x8d, 0xc6, 0x4e, 0xd2, 0x02, 0xfc, 0x92, 0xc2,
+ 0x90, 0xed, 0xaa, 0xb1, 0x72, 0xb6, 0xbb, 0x8f },
+ { 0x44, 0x34, 0x80, 0xfc, 0xbe, 0x45, 0xc5, 0x58, 0x6b, 0x82,
+ 0xb8, 0x99, 0x07, 0x6b, 0x98, 0x84, 0xc8, 0x9b, 0x91, 0xfd,
+ 0x83, 0xc1, 0xdc, 0x07, 0x66, 0x59, 0x4a, 0xaa, 0x83, 0x73,
+ 0x82, 0xda, 0x01, 0x1b, 0x25, 0x21, 0xa6, 0x0c, 0xfb, 0x6a,
+ 0x03, 0x7d, 0x13, 0x21, 0xb9, 0x9f, 0x4e, 0x3b, 0x8e, 0x55,
+ 0x09, 0x69, 0x7d, 0x7d, 0x95, 0x78, 0x81, 0x89, 0xe8, 0xb0,
+ 0x7c, 0x20, 0xbf, 0xd8, 0x36, 0x45, 0xbc, 0xb6, 0x33, 0x19,
+ 0xad, 0xac, 0xfe, 0x8c, 0x39, 0x0d, 0xbb, 0xa7, 0x55, 0x70,
+ 0x71, 0x00, 0x6f, 0x29, 0x04, 0x05, 0x7d, 0xce, 0x3f, 0xee,
+ 0x20, 0x4d, 0xf5, 0x50, 0x71, 0xbc, 0x84, 0xe5, 0x5b, 0x3e,
+ 0xe7, 0xc9, 0x9e, 0x15, 0xd1, 0x6e, 0x7d, 0x58, 0x8a, 0x3c,
+ 0x35, 0x64, 0x96, 0x56, 0x88, 0x15, 0x5c, 0xfe, 0x45, 0xfe,
+ 0x94, 0x4b, 0x47, 0xd8, 0xdf, 0x4e, 0xa5, 0xa3 },
+ { 0x97, 0x11, 0x8a, 0x88, 0xcf, 0xfa, 0xa7, 0xeb, 0xab, 0x6d,
+ 0x1e, 0xb0, 0xa1, 0x70, 0x03, 0x71, 0xb9, 0xd3, 0x55, 0xcf,
+ 0x8e, 0xb0, 0x3e, 0x6d, 0x9b, 0x6c, 0x22, 0x4b, 0xf6, 0xd7,
+ 0x2b, 0x58, 0xd5, 0xb1, 0x38, 0xd8, 0xc4, 0x42, 0xbe, 0x82,
+ 0xc2, 0xda, 0xda, 0x9e, 0x06, 0x5a, 0x8e, 0xe9, 0x38, 0x14,
+ 0x90, 0x71, 0xd3, 0x16, 0x05, 0xac, 0xdb, 0xef, 0x7c, 0x00,
+ 0xc1, 0x17, 0xa7, 0x8d, 0xa3, 0x86, 0x89, 0x17, 0xe7, 0x21,
+ 0xba, 0x7b, 0x24, 0x12, 0x84, 0xed, 0x24, 0x57, 0x2a, 0xc6,
+ 0xc2, 0xa9, 0xd0, 0xf2, 0xfb, 0x43, 0xa8, 0x6a, 0xb2, 0x29,
+ 0x65, 0x37, 0xfb, 0xfe, 0x9b, 0x77, 0xef, 0x3e, 0x6b, 0x31,
+ 0xd6, 0xf9, 0x61, 0x52, 0x42, 0xe2, 0xd0, 0xe4, 0x0f, 0xa5,
+ 0x47, 0x87, 0x4a, 0xec, 0x4f, 0x2e, 0x3e, 0x85, 0x7a, 0x7a,
+ 0xf8, 0xff, 0xff, 0xb4, 0x91, 0x14, 0x22, 0x1a },
+ { 0x17, 0xc0, 0x77, 0x8d, 0x4b, 0x71, 0xfa, 0x82, 0xd5, 0x6a,
+ 0x17, 0x7a, 0xa5, 0x73, 0x38, 0x7c, 0x30, 0xb5, 0x40, 0x5a,
+ 0x27, 0x0f, 0x45, 0xf6, 0x55, 0x4f, 0xe7, 0x63, 0xfe, 0x52,
+ 0xea, 0xe7, 0xdb, 0xa2, 0xba, 0x26, 0x85, 0xc3, 0xfc, 0x72,
+ 0xe4, 0xe7, 0x62, 0x99, 0x8a, 0x02, 0x23, 0xa5, 0xa4, 0x2c,
+ 0x02, 0xf4, 0x10, 0x2f, 0xee, 0x2a, 0xa2, 0x73, 0x00, 0x83,
+ 0x3b, 0x06, 0xef, 0xa5, 0x5b, 0xa7, 0x0a, 0x49, 0x8a, 0x88,
+ 0x2f, 0xf2, 0xb8, 0x58, 0x63, 0x7b, 0x14, 0xb3, 0xe5, 0x01,
+ 0xa8, 0xb0, 0xd8, 0x20, 0x3e, 0xf2, 0xa1, 0xc4, 0x9d, 0x35,
+ 0x2f, 0xbb, 0x0f, 0xbf, 0xb7, 0x81, 0xe7, 0x79, 0xa3, 0xca,
+ 0xa0, 0x20, 0x70, 0xb4, 0x24, 0xe0, 0xdd, 0x81, 0x04, 0x77,
+ 0x4f, 0xbf, 0x80, 0x83, 0xc8, 0x1b, 0xa9, 0x3a, 0x68, 0x66,
+ 0xbf, 0x9c, 0x59, 0xa2, 0xcd, 0xec, 0xb5, 0xd8 },
+ { 0x12, 0x19, 0xd5, 0xc8, 0x57, 0x1f, 0xe4, 0xc6, 0xd6, 0xce,
+ 0x84, 0xe1, 0xa4, 0x52, 0xed, 0x66, 0x9f, 0xfe, 0xc3, 0xa1,
+ 0xe2, 0xbf, 0x5d, 0x84, 0x6d, 0xd1, 0x2a, 0xe0, 0x1a, 0xd2,
+ 0x3a, 0x38, 0x5a, 0x8d, 0xb7, 0x9b, 0xa9, 0x6c, 0xc9, 0xa3,
+ 0x72, 0x3f, 0x43, 0x09, 0xa0, 0xff, 0xce, 0x0e, 0x7a, 0x0d,
+ 0x91, 0x57, 0x37, 0x85, 0x9a, 0x6a, 0x16, 0xe1, 0x2c, 0x45,
+ 0xe8, 0x6d, 0x5f, 0xd5, 0xf2, 0x24, 0x95, 0x2b, 0x18, 0x69,
+ 0x1c, 0x4a, 0x76, 0x8b, 0xca, 0x70, 0x05, 0x28, 0xbd, 0x40,
+ 0xa1, 0xa1, 0xde, 0xcd, 0x96, 0x7a, 0x2e, 0xca, 0x8c, 0x3f,
+ 0xa1, 0x77, 0xf5, 0xb0, 0x43, 0x77, 0x40, 0xfa, 0x45, 0x18,
+ 0xba, 0x09, 0xf3, 0xc4, 0xa2, 0xf5, 0xac, 0x9d, 0x9e, 0xbb,
+ 0xa9, 0x78, 0xc9, 0x88, 0x4e, 0x56, 0x65, 0x6e, 0xc5, 0x72,
+ 0x0e, 0x6d, 0xff, 0x1d, 0x27, 0x35, 0xe3, 0x7b },
+ { 0x2c, 0x8d, 0x7a, 0xb2, 0xd6, 0x57, 0xf2, 0x30, 0x13, 0x14,
+ 0xa8, 0x2f, 0x7e, 0x62, 0x6f, 0x42, 0x70, 0xb5, 0x7e, 0x1f,
+ 0x0b, 0xe2, 0x9e, 0xce, 0x76, 0xf9, 0x28, 0x39, 0x3a, 0x07,
+ 0x93, 0xf9, 0x3c, 0x29, 0x6b, 0x0d, 0xd2, 0x34, 0xa0, 0x7a,
+ 0x28, 0x65, 0xdd, 0x61, 0xcb, 0xa5, 0x7c, 0xc8, 0x43, 0x08,
+ 0xf7, 0x62, 0xa0, 0x4e, 0x6b, 0x87, 0x21, 0x6a, 0x61, 0xd0,
+ 0x7f, 0xac, 0x67, 0xc6, 0x95, 0xcd, 0x99, 0x90, 0xeb, 0x24,
+ 0xc3, 0x88, 0x14, 0x84, 0xbd, 0xb1, 0x8b, 0xac, 0x11, 0xd6,
+ 0x51, 0xd3, 0xd0, 0x75, 0xa9, 0x74, 0x3e, 0x6b, 0xff, 0xff,
+ 0xca, 0xd8, 0xe5, 0x80, 0xbd, 0xbd, 0x0f, 0x82, 0xb0, 0xed,
+ 0x8d, 0x15, 0x02, 0x74, 0xe6, 0x12, 0x7e, 0x51, 0x57, 0xbb,
+ 0x09, 0x09, 0x3a, 0x3a, 0xb3, 0x9d, 0x2f, 0x03, 0xe7, 0x73,
+ 0x43, 0xea, 0xa6, 0x7f, 0x26, 0x29, 0x69, 0xeb },
+ { 0x22, 0x99, 0xd2, 0x77, 0x4b, 0x09, 0xd9, 0x58, 0x96, 0xeb,
+ 0x70, 0x5a, 0x1b, 0x40, 0x4c, 0x44, 0x59, 0x60, 0x13, 0xdb,
+ 0x94, 0xa2, 0x0b, 0x11, 0xb0, 0xfd, 0x1c, 0xd5, 0xd1, 0xd3,
+ 0x98, 0xfb, 0xd4, 0x42, 0x8b, 0x2e, 0xed, 0x8c, 0xd5, 0x9a,
+ 0x74, 0x74, 0xbf, 0x0d, 0x77, 0xf8, 0x4a, 0x34, 0x6c, 0x98,
+ 0xd0, 0x5d, 0xc6, 0x7d, 0x6a, 0x8a, 0x69, 0xce, 0xd5, 0xaa,
+ 0xac, 0xa2, 0xd7, 0xef, 0xda, 0x89, 0x78, 0xbd, 0x29, 0xe3,
+ 0x7f, 0xeb, 0x11, 0x8a, 0xab, 0x77, 0x5a, 0x4d, 0xf3, 0x81,
+ 0x99, 0xda, 0xe4, 0x69, 0xd4, 0x5e, 0xbb, 0xa7, 0x8c, 0x4b,
+ 0x14, 0xdd, 0x9d, 0xf6, 0x43, 0x6a, 0x22, 0x9f, 0x89, 0xf5,
+ 0x8d, 0xd0, 0x96, 0x3f, 0x63, 0xe6, 0x65, 0xd8, 0x13, 0x10,
+ 0x10, 0x8d, 0xdf, 0x51, 0xea, 0xa5, 0x6e, 0xf8, 0x3b, 0x44,
+ 0x67, 0xcf, 0x58, 0x92, 0x08, 0x25, 0xe4, 0xd6 },
+ { 0x21, 0xac, 0x67, 0x79, 0x19, 0x36, 0x61, 0x8e, 0xaf, 0x9f,
+ 0xfa, 0x57, 0x27, 0xb4, 0x6c, 0x26, 0x97, 0x1b, 0x73, 0x6f,
+ 0x52, 0xca, 0x0d, 0x50, 0x71, 0xc4, 0x41, 0x35, 0xf0, 0xb6,
+ 0x59, 0x34, 0xc7, 0xad, 0x1d, 0x2b, 0x82, 0x1c, 0x44, 0x6b,
+ 0xe8, 0xd3, 0x8b, 0x48, 0x25, 0x31, 0x7e, 0x95, 0x0c, 0xf5,
+ 0x62, 0x91, 0xac, 0xe0, 0x07, 0x4e, 0x69, 0x25, 0xb1, 0xb3,
+ 0x04, 0x2d, 0xf4, 0x8e, 0x33, 0x6f, 0xd1, 0x3d, 0x91, 0x6e,
+ 0xe9, 0x8b, 0xed, 0x5d, 0x51, 0x89, 0xbe, 0xc4, 0xf8, 0xa0,
+ 0xdc, 0x96, 0x3f, 0x2d, 0x41, 0x1d, 0xb5, 0xf6, 0xa4, 0xb2,
+ 0x80, 0xcd, 0xe5, 0x3c, 0x01, 0xfd, 0x40, 0x5a, 0xe2, 0x87,
+ 0x8f, 0xcd, 0xc6, 0x8c, 0x58, 0x66, 0xd8, 0xe1, 0x3e, 0x9f,
+ 0x1d, 0xb2, 0xac, 0x19, 0x8f, 0x1e, 0xbf, 0x6d, 0xd3, 0x1e,
+ 0x5b, 0x9c, 0xd5, 0x8d, 0xc6, 0x43, 0x97, 0xe6 },
+ { 0x0e, 0x8e, 0xc1, 0xe7, 0x0e, 0x62, 0xd9, 0xd8, 0x66, 0x3d,
+ 0x88, 0xd6, 0x24, 0x48, 0x3a, 0x56, 0x01, 0x5f, 0x7e, 0x78,
+ 0x92, 0xc2, 0xe1, 0xbb, 0x30, 0x46, 0x3e, 0xe4, 0xe7, 0xf7,
+ 0xbe, 0x9f, 0x61, 0x22, 0x11, 0xdb, 0xee, 0x01, 0x64, 0xcd,
+ 0xc3, 0xf1, 0xc4, 0x31, 0xb2, 0x61, 0xca, 0x1c, 0xff, 0xa3,
+ 0x49, 0x6a, 0x3e, 0x60, 0x2f, 0x74, 0xfc, 0x0e, 0x1a, 0x45,
+ 0x61, 0x5a, 0x43, 0x89, 0x4f, 0x39, 0x89, 0x97, 0x0f, 0xf2,
+ 0x7b, 0x9c, 0x70, 0x97, 0x8a, 0x59, 0x03, 0x7c, 0x19, 0xb8,
+ 0x13, 0xd6, 0xf3, 0x75, 0xa0, 0xf2, 0x28, 0x14, 0xdf, 0xc1,
+ 0x9b, 0x09, 0xb3, 0x3c, 0x36, 0x25, 0x6f, 0xcd, 0x42, 0x36,
+ 0x38, 0x07, 0xb7, 0xd3, 0x49, 0x20, 0x33, 0xf8, 0x4d, 0xf5,
+ 0xd4, 0xb4, 0x12, 0x72, 0x24, 0x73, 0x97, 0xbd, 0xfc, 0x18,
+ 0xab, 0x42, 0x0e, 0x3f, 0x2d, 0x7f, 0xbc, 0xd2 },
+ { 0x65, 0x3a, 0x79, 0x5f, 0x5d, 0x10, 0x36, 0x35, 0xd8, 0x50,
+ 0xc1, 0xc0, 0x1b, 0x6b, 0x73, 0xfd, 0xe2, 0xa2, 0xbd, 0x12,
+ 0xf4, 0xb1, 0x3e, 0x5b, 0x76, 0xaa, 0x0f, 0x56, 0x86, 0x4d,
+ 0x83, 0x26, 0x58, 0x19, 0x2c, 0x86, 0xa2, 0x94, 0xa3, 0x25,
+ 0x67, 0xb1, 0x21, 0x7e, 0xd0, 0x77, 0x36, 0x66, 0xe1, 0x84,
+ 0x7a, 0x4c, 0x49, 0x5d, 0x83, 0x25, 0x78, 0x30, 0xae, 0x28,
+ 0x9b, 0x23, 0x7e, 0x91, 0x59, 0xef, 0x6c, 0xdd, 0xe0, 0xb9,
+ 0x14, 0x53, 0x42, 0xee, 0x03, 0x82, 0x4c, 0x67, 0xa7, 0x71,
+ 0xb7, 0x4b, 0x3d, 0xe7, 0x95, 0x9c, 0x48, 0xe3, 0x30, 0x78,
+ 0x5b, 0xd4, 0x88, 0xd2, 0x21, 0xa1, 0x31, 0x6d, 0x02, 0x3e,
+ 0xdd, 0x58, 0xa3, 0x15, 0x90, 0x34, 0x48, 0x20, 0xa5, 0x17,
+ 0x36, 0x17, 0x99, 0xac, 0x17, 0x5d, 0x66, 0x40, 0x07, 0x1a,
+ 0xa8, 0x8c, 0xcc, 0x29, 0x8a, 0x08, 0x78, 0xdd },
+ { 0x30, 0xdf, 0xc4, 0x7b, 0xd4, 0x44, 0x67, 0x5e, 0x08, 0x3f,
+ 0x65, 0xa5, 0xfb, 0x9d, 0x79, 0x76, 0x11, 0x18, 0x6d, 0x31,
+ 0x9a, 0x40, 0xda, 0x4b, 0xd2, 0x89, 0xeb, 0x4f, 0x27, 0xfb,
+ 0x0f, 0xd1, 0xf9, 0x94, 0xa1, 0x14, 0x7c, 0x6a, 0x42, 0xb1,
+ 0x46, 0xec, 0xbd, 0x3f, 0x1f, 0xef, 0x20, 0xe9, 0xbd, 0x75,
+ 0x73, 0x9c, 0xee, 0x7d, 0xaa, 0x26, 0xc9, 0x97, 0xf9, 0x3e,
+ 0xb2, 0x12, 0x5e, 0x8e, 0x14, 0xf9, 0x70, 0xcb, 0xdb, 0x45,
+ 0xd7, 0x63, 0x0b, 0x12, 0x83, 0x9a, 0xc5, 0xd1, 0xb1, 0x13,
+ 0xe2, 0x06, 0xb1, 0xd8, 0x1d, 0xb7, 0x25, 0xc7, 0x3a, 0xa7,
+ 0x04, 0xde, 0xe2, 0xb1, 0x2d, 0x52, 0xb0, 0xe5, 0x28, 0x8d,
+ 0x27, 0xf1, 0x31, 0xb5, 0xbc, 0xa7, 0xd7, 0xc3, 0xc9, 0x76,
+ 0x03, 0xd0, 0xb3, 0x5b, 0x8e, 0x5e, 0x7f, 0xa0, 0x2b, 0x60,
+ 0xcf, 0xe2, 0x89, 0x85, 0x50, 0xdc, 0xb1, 0x99 },
+ { 0x57, 0x2a, 0x59, 0x1f, 0x54, 0xc2, 0x12, 0xcf, 0xe1, 0x6f,
+ 0xe8, 0x72, 0x39, 0x7f, 0x25, 0x01, 0x15, 0x35, 0xc7, 0xda,
+ 0xae, 0x0f, 0xe2, 0x18, 0x9a, 0xc5, 0x2a, 0x4d, 0x40, 0x7a,
+ 0x3a, 0xa0, 0x98, 0x3a, 0xf1, 0x75, 0x25, 0x18, 0x49, 0x39,
+ 0x5d, 0xa6, 0x9e, 0x0b, 0xeb, 0x1a, 0xe2, 0x89, 0x27, 0x61,
+ 0x92, 0xbf, 0x07, 0xd7, 0xc3, 0xc8, 0x86, 0xe1, 0x14, 0xa6,
+ 0x2d, 0xdf, 0x7a, 0xc6, 0x17, 0x07, 0x3c, 0xe6, 0x3e, 0x2f,
+ 0x69, 0x84, 0xb7, 0xbe, 0x23, 0x36, 0xc4, 0xb7, 0x8e, 0x1c,
+ 0xa3, 0x51, 0x4b, 0x21, 0x98, 0x83, 0x11, 0x0f, 0xb1, 0xa3,
+ 0xdf, 0x7a, 0x30, 0x59, 0x06, 0x8e, 0xa2, 0xb9, 0xc2, 0x04,
+ 0x56, 0xa6, 0xa2, 0x14, 0xab, 0x07, 0x02, 0xdf, 0x8b, 0x53,
+ 0x35, 0x61, 0x25, 0x02, 0x7e, 0x54, 0xb4, 0xd4, 0xe8, 0x12,
+ 0xbc, 0xfc, 0x5a, 0xe2, 0x9e, 0xaa, 0xdf, 0xe8 },
+ { 0x65, 0xc2, 0xcb, 0xe1, 0xd8, 0xc8, 0x2c, 0x3c, 0x80, 0xc8,
+ 0x65, 0x53, 0x24, 0x91, 0x9a, 0x4e, 0x12, 0x0c, 0x6f, 0xbc,
+ 0x6c, 0x8b, 0x19, 0x0e, 0x81, 0x42, 0xdb, 0x5c, 0x90, 0xaf,
+ 0xd0, 0x7b, 0x6e, 0x3e, 0x49, 0x9d, 0x8d, 0x15, 0x76, 0x7a,
+ 0x90, 0x2f, 0xe9, 0x29, 0xf9, 0x08, 0xab, 0x43, 0xa3, 0x84,
+ 0x67, 0xdc, 0xe5, 0x3d, 0x1a, 0xa9, 0x15, 0xbc, 0xf3, 0xc6,
+ 0x11, 0xcb, 0x8c, 0x31, 0xf1, 0xd3, 0x62, 0x2b, 0x67, 0xf3,
+ 0x3f, 0x76, 0xb7, 0x05, 0xed, 0x61, 0x3d, 0x67, 0x4f, 0xe5,
+ 0xbb, 0xa5, 0x97, 0xce, 0xca, 0x03, 0x06, 0xd8, 0x6d, 0x96,
+ 0x71, 0xc0, 0x2f, 0xed, 0x95, 0x78, 0xbd, 0x3c, 0xbf, 0x9b,
+ 0xf2, 0x21, 0x26, 0xd4, 0xf9, 0xce, 0xb4, 0xb2, 0x3e, 0xef,
+ 0xd6, 0x90, 0x3f, 0x05, 0x43, 0x18, 0x32, 0x77, 0x33, 0xbc,
+ 0x49, 0x66, 0x84, 0x19, 0x09, 0xa5, 0x55, 0x3a },
+ { 0x83, 0x14, 0x40, 0xd5, 0x3b, 0xa7, 0x7f, 0x66, 0xd8, 0x05,
+ 0x50, 0x16, 0x0e, 0x78, 0x88, 0xb9, 0x25, 0x33, 0xad, 0x58,
+ 0xa0, 0xdc, 0xf4, 0xab, 0x43, 0x53, 0xd7, 0x2e, 0x1a, 0x09,
+ 0x98, 0x52, 0x46, 0xdb, 0x73, 0x8d, 0xdf, 0xae, 0x7a, 0x1a,
+ 0x78, 0x3e, 0xff, 0x1b, 0x94, 0xef, 0x7e, 0xd3, 0xa5, 0xc4,
+ 0xf1, 0xdc, 0x22, 0x9b, 0xd3, 0xde, 0x8c, 0x3c, 0xa3, 0x49,
+ 0x73, 0xe1, 0xd2, 0xf1, 0x5e, 0x34, 0xe3, 0x00, 0x47, 0x73,
+ 0x81, 0x83, 0x92, 0xea, 0x15, 0xec, 0x95, 0x01, 0x17, 0x70,
+ 0x82, 0x9b, 0xc6, 0xb3, 0x41, 0x3f, 0x57, 0x9e, 0xb6, 0x88,
+ 0x42, 0x77, 0x08, 0x45, 0x2d, 0x44, 0x79, 0xc1, 0x62, 0xe5,
+ 0x67, 0x9d, 0xd1, 0x58, 0x76, 0x47, 0x2c, 0xf6, 0x6b, 0xa0,
+ 0xee, 0xd7, 0x27, 0xdc, 0x3b, 0x0a, 0x86, 0xe8, 0x62, 0x45,
+ 0x68, 0x4c, 0xda, 0x20, 0xa6, 0x60, 0xbb, 0x63 },
+ { 0x50, 0x4c, 0x3a, 0x8a, 0x6d, 0x5f, 0x45, 0x66, 0x4a, 0x98,
+ 0x5a, 0x70, 0xe1, 0x5a, 0x28, 0x15, 0x38, 0x53, 0x99, 0xcd,
+ 0xbc, 0xf1, 0x19, 0xca, 0x57, 0x39, 0xac, 0x8f, 0x98, 0x5f,
+ 0xb4, 0x6d, 0xe9, 0x56, 0x63, 0xcc, 0x1b, 0x41, 0x1e, 0x3e,
+ 0x3c, 0xd1, 0x7f, 0x7f, 0x82, 0x14, 0x7b, 0x71, 0x7e, 0x0c,
+ 0x7a, 0x3c, 0x64, 0xca, 0xdf, 0xc6, 0x04, 0x88, 0x38, 0x2f,
+ 0x48, 0x53, 0x6b, 0x3b, 0xc9, 0x97, 0x7d, 0xb5, 0x63, 0x8c,
+ 0xe1, 0x1a, 0xea, 0x3f, 0xce, 0x98, 0x3d, 0xe0, 0x78, 0xdd,
+ 0x73, 0x5b, 0x86, 0x0a, 0x10, 0x1e, 0x85, 0x17, 0x92, 0x9d,
+ 0x7f, 0x66, 0xdf, 0xd2, 0x7a, 0x66, 0xc4, 0x5c, 0x28, 0xe6,
+ 0x1d, 0x3e, 0x44, 0xf0, 0xe8, 0x97, 0xf3, 0xe8, 0x82, 0x0b,
+ 0x3c, 0x0d, 0x5d, 0x06, 0x6e, 0x29, 0xd0, 0xfa, 0x46, 0xac,
+ 0xf4, 0x3e, 0x2e, 0x32, 0xf6, 0x11, 0xb2, 0xda },
+ { 0x49, 0x6e, 0x46, 0x99, 0xc7, 0x1d, 0x21, 0xd2, 0xc2, 0x7a,
+ 0xf0, 0xb1, 0x69, 0xf5, 0x6a, 0xdd, 0x38, 0xca, 0xf7, 0xd0,
+ 0x77, 0xfd, 0xc5, 0x20, 0xbf, 0x2e, 0xa6, 0xc9, 0xf8, 0x43,
+ 0x04, 0x22, 0x5e, 0xca, 0xc3, 0xe5, 0x6d, 0xe9, 0x37, 0xdc,
+ 0x2a, 0xe6, 0x84, 0xde, 0x55, 0x37, 0xb7, 0xda, 0x85, 0xa7,
+ 0xa9, 0xc3, 0xe6, 0xe2, 0x8e, 0xac, 0xbc, 0x70, 0xb3, 0xce,
+ 0xa6, 0x96, 0x73, 0xea, 0xb3, 0x5e, 0x56, 0x7e, 0xa6, 0xe8,
+ 0xa3, 0xbb, 0x4c, 0x23, 0xc6, 0xb6, 0x67, 0x0b, 0x27, 0x02,
+ 0xa2, 0xdc, 0x00, 0x1d, 0x7e, 0xe8, 0x1e, 0xe1, 0x6a, 0xd3,
+ 0x89, 0x56, 0xaa, 0xbc, 0xc6, 0x74, 0x29, 0x83, 0x24, 0x30,
+ 0xe5, 0xa1, 0x29, 0xed, 0x23, 0x4d, 0x24, 0x1c, 0x43, 0x7c,
+ 0xe2, 0x5f, 0x98, 0x5c, 0xff, 0x38, 0x50, 0x94, 0x74, 0xe3,
+ 0x00, 0xb5, 0x52, 0x83, 0xb8, 0xfa, 0x53, 0xc7 },
+ { 0x13, 0x38, 0x91, 0x73, 0x13, 0x03, 0x7f, 0xe8, 0x4f, 0x2b,
+ 0x5c, 0xcf, 0xcb, 0x37, 0x44, 0xb5, 0x35, 0x4c, 0xdc, 0xdb,
+ 0xe5, 0xf0, 0x69, 0x52, 0xc1, 0x4b, 0x21, 0x5e, 0xb0, 0xd6,
+ 0x86, 0x3a, 0x8b, 0xa0, 0xd9, 0xe9, 0xae, 0xab, 0x51, 0xf9,
+ 0xd6, 0x7a, 0xac, 0xaf, 0x76, 0x5b, 0xa2, 0x68, 0xce, 0xb4,
+ 0x0e, 0xdc, 0x95, 0x11, 0x67, 0xb7, 0x97, 0xbf, 0x6a, 0x54,
+ 0x22, 0x03, 0xd5, 0xc4, 0x5a, 0x21, 0xec, 0xe6, 0x2c, 0xd6,
+ 0x40, 0xc5, 0xbd, 0x01, 0xfa, 0x86, 0xbb, 0x04, 0x79, 0x3b,
+ 0xc4, 0x63, 0xbd, 0xa6, 0x17, 0xc0, 0x81, 0xb8, 0x40, 0xbf,
+ 0xd0, 0x80, 0x81, 0xf3, 0x21, 0x6a, 0xbc, 0x85, 0x97, 0x52,
+ 0x36, 0x86, 0xbd, 0xcc, 0x65, 0x9b, 0xcf, 0xaf, 0x48, 0x33,
+ 0xe0, 0x9b, 0xc2, 0xe3, 0x76, 0x84, 0x0e, 0xb2, 0xa6, 0x14,
+ 0xba, 0x14, 0xfc, 0x82, 0x9f, 0xa9, 0x34, 0x67 },
+ { 0x42, 0x2e, 0xb5, 0x73, 0xf3, 0x83, 0x3f, 0xbd, 0x4c, 0x81,
+ 0x02, 0xb4, 0x6d, 0xa1, 0xf3, 0x45, 0xd2, 0xce, 0xfa, 0x09,
+ 0x69, 0x5e, 0x3a, 0x02, 0x02, 0xc5, 0x10, 0x4d, 0x4d, 0xea,
+ 0x47, 0x96, 0x50, 0xf0, 0xc0, 0xa6, 0x04, 0x85, 0xdf, 0xf4,
+ 0x4b, 0xb2, 0x95, 0x2e, 0x55, 0xfb, 0xdb, 0xac, 0x9e, 0x7a,
+ 0x9b, 0x46, 0x3b, 0x45, 0xfe, 0xa5, 0xae, 0xc0, 0xfc, 0xb2,
+ 0x6b, 0xc8, 0xaa, 0x2a, 0x68, 0x07, 0x41, 0x72, 0x54, 0x33,
+ 0x04, 0xef, 0x0b, 0xc4, 0x93, 0xf9, 0x50, 0xa3, 0x4a, 0x7b,
+ 0xec, 0xc4, 0xcf, 0xb0, 0x26, 0x09, 0x90, 0xc8, 0xbb, 0x57,
+ 0x76, 0x2d, 0x38, 0xf3, 0x7e, 0x01, 0x81, 0xe3, 0x4e, 0xb9,
+ 0xc7, 0xce, 0xa9, 0x5c, 0x4b, 0xcd, 0x41, 0x9f, 0xde, 0x8e,
+ 0x53, 0x14, 0xfd, 0xac, 0x17, 0xbc, 0x44, 0xae, 0x2a, 0xc6,
+ 0xee, 0x68, 0x06, 0x40, 0x45, 0x00, 0x3c, 0xd1 },
+ { 0x36, 0x85, 0x41, 0xcf, 0x2c, 0x25, 0x25, 0x82, 0xcf, 0xba,
+ 0x27, 0xd7, 0xa0, 0xda, 0x2d, 0xc6, 0xa9, 0xfb, 0xbb, 0x4c,
+ 0xb7, 0xfd, 0x2b, 0x05, 0x7d, 0x19, 0xb9, 0xc2, 0x72, 0x79,
+ 0x99, 0xff, 0x09, 0xfe, 0xbc, 0x9c, 0x74, 0x73, 0x12, 0xe1,
+ 0x40, 0xf1, 0xc7, 0xe1, 0x66, 0xa3, 0xf2, 0xbf, 0xee, 0x63,
+ 0xfa, 0x8b, 0x88, 0x9d, 0xf8, 0xbc, 0x26, 0xea, 0x5a, 0x54,
+ 0xd6, 0x60, 0x59, 0xfe, 0xf2, 0xe2, 0x0c, 0xb4, 0x5b, 0x0f,
+ 0xd3, 0xad, 0xc8, 0x9e, 0x89, 0x20, 0xcb, 0xa0, 0x3c, 0xdc,
+ 0xf2, 0xa6, 0xba, 0x41, 0xda, 0xfb, 0x73, 0x6a, 0x72, 0x53,
+ 0x76, 0xac, 0x54, 0xb1, 0x27, 0x23, 0xcf, 0x7c, 0x94, 0xe2,
+ 0x64, 0xea, 0x58, 0x03, 0x57, 0xc1, 0xe9, 0x19, 0x07, 0x28,
+ 0x14, 0x59, 0xb0, 0x86, 0x1f, 0x6d, 0x97, 0x14, 0xba, 0x0e,
+ 0xac, 0x59, 0x2e, 0xb6, 0xa6, 0xad, 0x3f, 0x47 },
+ { 0x59, 0xa5, 0xbf, 0x59, 0x22, 0x26, 0x13, 0x34, 0xb8, 0x97,
+ 0x78, 0x80, 0x22, 0x41, 0xa5, 0x66, 0x07, 0x3b, 0xf8, 0x69,
+ 0xc7, 0xf9, 0x27, 0xe9, 0x09, 0xd8, 0xcf, 0x2d, 0x86, 0xa5,
+ 0x86, 0xf4, 0x16, 0x69, 0x78, 0x6a, 0x97, 0xe9, 0x4c, 0x11,
+ 0xe2, 0x64, 0xfa, 0x41, 0xb6, 0xa1, 0x3d, 0x00, 0xb0, 0x0d,
+ 0xbf, 0x9d, 0x2a, 0xc1, 0xaf, 0x48, 0xe6, 0x7c, 0x10, 0x2a,
+ 0xf5, 0x15, 0xe2, 0x3e, 0x34, 0xb4, 0x73, 0xf0, 0x65, 0x4b,
+ 0xe2, 0xf2, 0xd0, 0x20, 0x8a, 0x03, 0xbd, 0x07, 0xd8, 0x77,
+ 0xd5, 0xa6, 0xf2, 0xaf, 0xac, 0x06, 0x7f, 0xe8, 0x79, 0x75,
+ 0x41, 0xb6, 0x0e, 0x84, 0x2d, 0xc2, 0x69, 0xb5, 0x3c, 0x2a,
+ 0xaf, 0xc8, 0xdf, 0xc2, 0x4e, 0x6a, 0xe1, 0x8f, 0x08, 0x0f,
+ 0x79, 0x5b, 0x1b, 0x67, 0x7d, 0xe5, 0xac, 0xfa, 0x33, 0x3a,
+ 0x51, 0x0d, 0x3c, 0x9e, 0x22, 0x79, 0x9d, 0x37 },
+ { 0x46, 0x75, 0x64, 0xc1, 0x43, 0xeb, 0x79, 0x9c, 0xf1, 0x4e,
+ 0xf6, 0x18, 0xd3, 0xd3, 0xe0, 0xf8, 0x04, 0xda, 0x45, 0xf8,
+ 0x98, 0x4c, 0xfd, 0x36, 0x8d, 0x0b, 0x5c, 0xbe, 0x4a, 0xcc,
+ 0x5f, 0x4d, 0x77, 0xe7, 0xe0, 0x79, 0xb1, 0x3f, 0x3b, 0xd1,
+ 0x36, 0xdd, 0xc2, 0x37, 0x2a, 0xaa, 0x91, 0x35, 0xaa, 0x1b,
+ 0x05, 0xe0, 0x39, 0x84, 0x8b, 0xc9, 0x9c, 0xaa, 0x06, 0xb7,
+ 0xa6, 0x15, 0x6f, 0x8a, 0x6a, 0x6a, 0x71, 0xaa, 0xda, 0xdb,
+ 0x47, 0xfb, 0xf9, 0x38, 0x60, 0xd0, 0x94, 0x22, 0x81, 0x00,
+ 0x82, 0x67, 0xfd, 0x78, 0xf8, 0xdd, 0x3c, 0x6c, 0x08, 0xbe,
+ 0xe9, 0xf1, 0xd9, 0x1b, 0x9a, 0xa0, 0xda, 0x93, 0xcf, 0xcc,
+ 0xda, 0xa7, 0xd3, 0x97, 0x07, 0x88, 0x87, 0x67, 0xa9, 0xd4,
+ 0x6a, 0x7f, 0x18, 0x6c, 0x1a, 0xbc, 0xeb, 0x96, 0x99, 0x72,
+ 0xe9, 0xd1, 0xc9, 0x1e, 0x81, 0x34, 0x71, 0x91 },
+ { 0x8a, 0x0d, 0xee, 0x16, 0x4e, 0xe9, 0x84, 0xd5, 0x0d, 0x0f,
+ 0x7a, 0xdb, 0xed, 0x6a, 0x1e, 0x03, 0x17, 0x73, 0xf0, 0x16,
+ 0x7b, 0x7c, 0x50, 0xd9, 0x06, 0x8f, 0x39, 0xcb, 0x4f, 0x81,
+ 0xe0, 0x9e, 0xfe, 0x8d, 0x72, 0x8c, 0x7a, 0x03, 0x62, 0x18,
+ 0xf3, 0x16, 0x77, 0x32, 0x2f, 0x15, 0xb8, 0x50, 0x9f, 0x71,
+ 0xbc, 0x0c, 0xa5, 0xd2, 0xa0, 0x06, 0xa2, 0x8f, 0xe1, 0x28,
+ 0xc7, 0x9e, 0xdc, 0xb2, 0x8e, 0xb4, 0x8b, 0x15, 0x01, 0x1b,
+ 0xc6, 0xf3, 0xac, 0x92, 0xb6, 0xa2, 0xea, 0x87, 0x74, 0x86,
+ 0x61, 0xc5, 0x03, 0x18, 0x94, 0xd3, 0x5c, 0x61, 0xa2, 0xfe,
+ 0xb4, 0xaf, 0x68, 0xa2, 0xb9, 0xb0, 0x32, 0x23, 0x5f, 0xc1,
+ 0x43, 0xba, 0xec, 0x39, 0x90, 0x95, 0xd5, 0x75, 0x6d, 0x20,
+ 0xb8, 0xaa, 0x03, 0x7f, 0x33, 0xaf, 0x92, 0xdc, 0x47, 0x52,
+ 0x8d, 0x72, 0x59, 0x04, 0xb6, 0xff, 0xf5, 0xd7 },
+ { 0x7b, 0x04, 0xb5, 0xd2, 0xee, 0x97, 0xce, 0x23, 0x2c, 0xe7,
+ 0xfe, 0x7d, 0xb6, 0xf6, 0xbe, 0xd2, 0x9e, 0x9d, 0xb1, 0x9f,
+ 0xc1, 0xf0, 0x00, 0x73, 0x77, 0x78, 0xa9, 0x66, 0x3f, 0xe0,
+ 0xa1, 0x7c, 0xe8, 0x9b, 0xbc, 0x1d, 0x7b, 0x62, 0x84, 0x03,
+ 0xf1, 0xe8, 0x0c, 0x84, 0x55, 0x4c, 0xc2, 0x77, 0xf9, 0x7c,
+ 0xfd, 0x0e, 0x7e, 0x20, 0xa2, 0xc3, 0x31, 0x0d, 0x91, 0xf1,
+ 0xe3, 0xe1, 0x81, 0x09, 0xc0, 0x36, 0x7e, 0xf8, 0xbb, 0xaa,
+ 0x1e, 0x8c, 0x6a, 0x8e, 0x45, 0x3e, 0xc7, 0xee, 0x80, 0x8d,
+ 0xdb, 0x8d, 0x1b, 0x57, 0xc9, 0x1e, 0x21, 0x5f, 0x56, 0xa7,
+ 0x85, 0xf9, 0x40, 0x44, 0x5e, 0x43, 0xbb, 0xb4, 0x6a, 0xa6,
+ 0x3f, 0x19, 0x61, 0xe2, 0x14, 0xc4, 0xc7, 0x51, 0xa4, 0x0c,
+ 0xce, 0x36, 0xb8, 0x08, 0x4d, 0x9f, 0xe8, 0x6c, 0x30, 0x05,
+ 0x50, 0x49, 0x91, 0xbf, 0x47, 0x36, 0x6e, 0x6f },
+ { 0x1c, 0x6a, 0x95, 0xa4, 0xc9, 0x9b, 0xe3, 0x1c, 0x51, 0x5b,
+ 0x08, 0x1c, 0x9c, 0x7b, 0x27, 0x2c, 0x4f, 0x14, 0xd0, 0x32,
+ 0x37, 0x86, 0x97, 0x7a, 0xd8, 0x51, 0x19, 0xa0, 0xa8, 0xd8,
+ 0x18, 0x22, 0xe5, 0x46, 0x5a, 0x55, 0x33, 0x88, 0x63, 0x72,
+ 0x3a, 0xe2, 0x1b, 0x23, 0xa6, 0xdd, 0x80, 0x2f, 0xcd, 0x4d,
+ 0x50, 0x89, 0xc6, 0x22, 0xd6, 0xe3, 0x07, 0x29, 0x02, 0xd7,
+ 0x66, 0xe3, 0xad, 0xf0, 0x0a, 0xa2, 0xac, 0x6e, 0xcf, 0xa5,
+ 0x18, 0x57, 0x2e, 0xc6, 0xf0, 0xbb, 0xe1, 0xbb, 0xef, 0x41,
+ 0x60, 0x77, 0x38, 0xfb, 0xe0, 0xc1, 0x48, 0xec, 0xc7, 0x35,
+ 0x17, 0x31, 0xc3, 0xc3, 0xc3, 0x7c, 0x83, 0x3a, 0x10, 0x13,
+ 0xe9, 0x56, 0xd5, 0x1f, 0x3d, 0x56, 0x68, 0x61, 0xe7, 0x78,
+ 0x51, 0xe0, 0x1a, 0x73, 0x4c, 0x5e, 0x8e, 0xb8, 0x10, 0x97,
+ 0x5b, 0x54, 0x6b, 0xc7, 0x82, 0xc5, 0xfa, 0xf8 },
+ { 0x72, 0x70, 0x8a, 0x02, 0x30, 0xa8, 0x64, 0xc9, 0xa5, 0xc0,
+ 0x9c, 0x84, 0x14, 0xf6, 0x87, 0x9c, 0xd4, 0xb3, 0x91, 0x9e,
+ 0x08, 0x18, 0xe4, 0xbe, 0x4c, 0xec, 0x87, 0x09, 0xe6, 0x56,
+ 0x25, 0xfb, 0x5c, 0x91, 0x22, 0x6e, 0xba, 0x9a, 0xbd, 0xa3,
+ 0x2a, 0x46, 0x48, 0x81, 0x34, 0xbd, 0x9a, 0xf1, 0x83, 0x6f,
+ 0x61, 0x64, 0x4b, 0x70, 0xab, 0x45, 0x99, 0xdd, 0x0a, 0xd6,
+ 0xdb, 0xbb, 0xa8, 0xfe, 0x47, 0x5a, 0x79, 0x23, 0xb7, 0x5f,
+ 0x3b, 0x76, 0xf4, 0xaa, 0xda, 0xb8, 0x1a, 0x1d, 0x9f, 0xb1,
+ 0x6f, 0x87, 0xbd, 0xf4, 0x75, 0xcb, 0xad, 0x1f, 0x92, 0xc9,
+ 0xc0, 0x98, 0xf0, 0x81, 0xd9, 0x27, 0xf4, 0x12, 0xab, 0x39,
+ 0x82, 0x48, 0x9e, 0x27, 0xae, 0xf5, 0xd2, 0xc4, 0xcc, 0xad,
+ 0xe8, 0x48, 0x82, 0x9c, 0x18, 0x23, 0x4d, 0x17, 0xde, 0x1c,
+ 0xa6, 0xb1, 0x4a, 0xd5, 0xc2, 0x82, 0x13, 0x63 },
+ { 0x74, 0x91, 0xc7, 0x4c, 0x73, 0x26, 0x5d, 0x21, 0x7d, 0xb5,
+ 0x5c, 0x0b, 0x43, 0x69, 0x51, 0x13, 0x95, 0x25, 0xc4, 0x73,
+ 0x73, 0x46, 0x7e, 0x9d, 0xf1, 0x69, 0xd3, 0xcc, 0xfa, 0xe1,
+ 0x03, 0xf7, 0xc8, 0x65, 0xf9, 0xfb, 0x61, 0xa8, 0x5b, 0xd5,
+ 0x9e, 0x08, 0x18, 0x69, 0xf7, 0x09, 0x69, 0x1c, 0xcf, 0xe8,
+ 0xb5, 0xce, 0xbb, 0x16, 0xb5, 0x15, 0x35, 0x5e, 0xb6, 0xe2,
+ 0x3e, 0x5c, 0x1b, 0x2a, 0xdb, 0x62, 0xd5, 0xb0, 0xb3, 0x5c,
+ 0x93, 0x65, 0x2b, 0x59, 0x06, 0x49, 0xc9, 0x79, 0x3e, 0x1c,
+ 0x73, 0x3d, 0xa7, 0x13, 0xce, 0xc6, 0xf4, 0x32, 0xe2, 0x41,
+ 0x6c, 0x2a, 0xbb, 0x04, 0x3d, 0xa3, 0x82, 0x4c, 0x71, 0x46,
+ 0x90, 0x88, 0x08, 0x81, 0xd7, 0x0f, 0x0f, 0xee, 0x0e, 0x28,
+ 0x78, 0x5c, 0xa1, 0xba, 0xe0, 0x9c, 0x7f, 0x9d, 0x45, 0xba,
+ 0x4f, 0x33, 0xc0, 0xb1, 0xf3, 0x4a, 0x46, 0x6c },
+ { 0x8b, 0xcf, 0xd3, 0xe5, 0x74, 0x17, 0x68, 0x41, 0x68, 0x29,
+ 0xd1, 0xc2, 0x68, 0x90, 0x6b, 0x76, 0xb7, 0x32, 0x9f, 0xab,
+ 0xbc, 0xe6, 0x86, 0x64, 0xcb, 0x59, 0x14, 0x93, 0xc6, 0xe8,
+ 0xdc, 0xbb, 0x00, 0xfd, 0x4b, 0x01, 0x0b, 0x3b, 0xa2, 0x2e,
+ 0xe5, 0x48, 0x7e, 0x25, 0xd3, 0xdd, 0x4a, 0xbd, 0x1f, 0xda,
+ 0x9f, 0x37, 0xc8, 0x5d, 0x3c, 0xb9, 0xd6, 0xc4, 0x70, 0x9f,
+ 0x01, 0x2a, 0xa3, 0xba, 0x69, 0xe7, 0x57, 0x84, 0xd9, 0xfc,
+ 0x5a, 0xdc, 0x93, 0xe2, 0x95, 0xc8, 0x59, 0x74, 0xb2, 0x01,
+ 0xda, 0xa7, 0xd8, 0x98, 0xe4, 0x2b, 0xcd, 0x5a, 0x2d, 0xfb,
+ 0x29, 0xee, 0x59, 0xef, 0x9c, 0xed, 0x31, 0x7c, 0xcf, 0x6b,
+ 0xae, 0xb8, 0x2c, 0x8e, 0xac, 0x86, 0xc5, 0x8c, 0xd6, 0x22,
+ 0x19, 0xa1, 0x1b, 0x8a, 0xc6, 0x33, 0xba, 0x4b, 0x26, 0x0b,
+ 0x31, 0x2e, 0xd5, 0xbf, 0x80, 0xd2, 0xb9, 0x4d },
+ { 0x53, 0xca, 0xdc, 0xf7, 0xbd, 0x37, 0xab, 0x49, 0x3e, 0x18,
+ 0xd1, 0xe4, 0x90, 0x5a, 0x93, 0x78, 0xbd, 0x78, 0x01, 0x0e,
+ 0x1d, 0xb9, 0x32, 0xad, 0xf1, 0x4d, 0xda, 0x81, 0x52, 0x89,
+ 0x04, 0x18, 0x6f, 0x54, 0x25, 0x09, 0x05, 0x7f, 0xe9, 0x1e,
+ 0xd1, 0xe5, 0xf8, 0xaf, 0x67, 0x1e, 0xc3, 0x79, 0xd9, 0xe8,
+ 0xd2, 0x06, 0x40, 0x22, 0xa6, 0x91, 0x09, 0xd7, 0x97, 0x0b,
+ 0x50, 0x74, 0x62, 0x57, 0x83, 0x44, 0x6b, 0x89, 0x6a, 0xf2,
+ 0x0e, 0xad, 0xd5, 0x8b, 0x3d, 0xf2, 0x2f, 0x58, 0x63, 0x89,
+ 0x0a, 0x06, 0x96, 0x48, 0x27, 0xdf, 0xfd, 0x4f, 0x15, 0x52,
+ 0x7e, 0x5e, 0x1f, 0x99, 0x22, 0x27, 0x53, 0x65, 0xe0, 0xd8,
+ 0x77, 0x92, 0x47, 0x87, 0xb9, 0x37, 0xf7, 0xc3, 0xc0, 0x68,
+ 0xba, 0x16, 0x95, 0xf0, 0xb2, 0xf1, 0x11, 0x87, 0x08, 0x33,
+ 0x06, 0x88, 0x27, 0x34, 0xd3, 0xc8, 0xc3, 0x14 },
+ { 0x90, 0x84, 0x99, 0x64, 0xbf, 0x8c, 0x62, 0xb1, 0x69, 0xbd,
+ 0x75, 0xe9, 0xc3, 0x2d, 0x10, 0x46, 0x75, 0x42, 0xa5, 0xae,
+ 0xb6, 0x9a, 0x97, 0x60, 0x10, 0x6f, 0x19, 0x0a, 0xa6, 0x50,
+ 0xec, 0x5c, 0x36, 0x94, 0x14, 0x85, 0x10, 0xf2, 0x62, 0x24,
+ 0x3d, 0xcd, 0xb9, 0xd2, 0x1e, 0x79, 0x42, 0x9e, 0xca, 0xf6,
+ 0x78, 0x4b, 0x49, 0x1f, 0x2b, 0xed, 0x01, 0x8b, 0x4e, 0xab,
+ 0x9e, 0x42, 0x87, 0x9c, 0x61, 0x75, 0x2e, 0x59, 0xda, 0x55,
+ 0xdd, 0x53, 0x4e, 0x10, 0x64, 0x82, 0x23, 0x96, 0x24, 0xd1,
+ 0x8c, 0x1e, 0x58, 0x67, 0x7d, 0xc9, 0xe5, 0x95, 0xab, 0xa6,
+ 0x79, 0x4b, 0xb1, 0x73, 0xb3, 0x17, 0xb3, 0x01, 0x83, 0x45,
+ 0xe2, 0x2b, 0x6a, 0x33, 0x64, 0x91, 0xb0, 0xf8, 0x12, 0x20,
+ 0x6d, 0x15, 0xd8, 0x86, 0x60, 0x6c, 0x88, 0x8a, 0xbf, 0x67,
+ 0x1b, 0xb5, 0xed, 0xf7, 0x5e, 0x53, 0xd0, 0xff },
+ { 0x3d, 0x7f, 0x6f, 0xfa, 0x46, 0x8c, 0xd7, 0xe8, 0xc2, 0xb7,
+ 0x5b, 0xe4, 0x73, 0x58, 0x0d, 0x22, 0xd4, 0xed, 0xbd, 0x5e,
+ 0x08, 0xdc, 0x4c, 0xc0, 0xcd, 0xee, 0x18, 0xf0, 0xe9, 0x3c,
+ 0x92, 0x68, 0x3e, 0x19, 0x49, 0xab, 0xf6, 0xb7, 0xde, 0x33,
+ 0xf6, 0x86, 0x22, 0x09, 0xc4, 0x21, 0xfb, 0x7a, 0xbd, 0x86,
+ 0xd2, 0xca, 0xc4, 0x10, 0x12, 0x4b, 0x49, 0xd3, 0x2d, 0x7b,
+ 0x87, 0x5e, 0xc5, 0x16, 0xc9, 0x21, 0xb3, 0x37, 0x60, 0x89,
+ 0xa4, 0xf2, 0x96, 0xfd, 0xa5, 0x0e, 0xbb, 0x5a, 0x42, 0xf8,
+ 0xf9, 0xb4, 0x38, 0x2d, 0x4e, 0x62, 0x42, 0x3e, 0x6e, 0x67,
+ 0xfe, 0xbd, 0x7c, 0x71, 0x48, 0x7c, 0x1b, 0x0c, 0xbb, 0x8f,
+ 0x67, 0x72, 0xde, 0x9a, 0x92, 0xa9, 0x3a, 0x9d, 0xa5, 0x1a,
+ 0x17, 0x88, 0x18, 0x48, 0x62, 0x64, 0x9d, 0xb5, 0xf0, 0x56,
+ 0xb1, 0x39, 0x0c, 0xf6, 0x5a, 0x93, 0xc6, 0x61 },
+ { 0x8f, 0xb1, 0x2d, 0x3f, 0x6d, 0xde, 0x74, 0xe6, 0x40, 0x99,
+ 0x4d, 0x6f, 0xfd, 0x43, 0x4e, 0x7c, 0x3e, 0x18, 0xc4, 0xfd,
+ 0x22, 0x54, 0xab, 0xee, 0x30, 0x3f, 0x9e, 0xb9, 0x1d, 0x16,
+ 0xa5, 0x55, 0x3f, 0x06, 0x4e, 0xd4, 0x51, 0x1e, 0x60, 0x19,
+ 0x56, 0x75, 0x28, 0xe3, 0x9c, 0x9c, 0x60, 0x17, 0xb5, 0x41,
+ 0x92, 0x03, 0x94, 0x92, 0xf2, 0x3a, 0x5f, 0xc6, 0x89, 0x35,
+ 0x54, 0x8b, 0xa5, 0x62, 0x55, 0x77, 0x1b, 0xf5, 0x55, 0x65,
+ 0x16, 0x33, 0x65, 0x9a, 0x34, 0x2c, 0xd8, 0x3c, 0x21, 0xf4,
+ 0x56, 0x12, 0x46, 0x7f, 0x7f, 0x19, 0x5b, 0x60, 0x85, 0x19,
+ 0xdf, 0x2b, 0xb2, 0xae, 0x4d, 0x82, 0xbc, 0x69, 0x0a, 0xf5,
+ 0x42, 0xdc, 0xe6, 0x8e, 0x56, 0x68, 0x0b, 0x08, 0x90, 0xfe,
+ 0xed, 0xc9, 0x9d, 0x75, 0x9d, 0xa6, 0x97, 0x03, 0x38, 0xdf,
+ 0xea, 0x7b, 0x29, 0x0c, 0xdf, 0xfb, 0xd5, 0xd1 },
+ { 0x3f, 0xcc, 0x67, 0x31, 0x75, 0xd2, 0x37, 0xb1, 0x4f, 0x93,
+ 0x03, 0xa2, 0x06, 0xff, 0x34, 0x53, 0xbe, 0x94, 0x6a, 0x59,
+ 0x19, 0xab, 0x1c, 0x97, 0xe7, 0x85, 0x8e, 0xcd, 0x37, 0x59,
+ 0x81, 0xec, 0x9b, 0x64, 0x3e, 0x77, 0x86, 0x7c, 0xa0, 0xe9,
+ 0x5f, 0x20, 0xfd, 0x2e, 0x4f, 0x47, 0x49, 0x9d, 0xaf, 0x77,
+ 0x1f, 0x6d, 0xfe, 0x23, 0x9f, 0x83, 0x29, 0xdd, 0x85, 0x0a,
+ 0x26, 0x8a, 0x5a, 0xf7, 0x87, 0x89, 0x69, 0x96, 0x29, 0x32,
+ 0xfb, 0x89, 0x13, 0x58, 0xf9, 0x7b, 0x4c, 0x2f, 0x13, 0x07,
+ 0x14, 0x68, 0x1a, 0x14, 0xf6, 0xf5, 0x80, 0xa0, 0x4a, 0x2b,
+ 0x69, 0x6a, 0x71, 0x6b, 0xa4, 0xdd, 0xe8, 0x9f, 0xfa, 0xd0,
+ 0x57, 0x8c, 0xae, 0x91, 0x4f, 0x21, 0x28, 0x23, 0x07, 0x8a,
+ 0xc3, 0xef, 0x45, 0x3e, 0x09, 0xf0, 0xb8, 0x7b, 0x7e, 0x4d,
+ 0x6c, 0x63, 0x81, 0xa2, 0x29, 0x3c, 0xb7, 0xa4 },
+ { 0x64, 0x51, 0x46, 0xfd, 0xc7, 0x15, 0x1c, 0x34, 0xd4, 0x13,
+ 0x45, 0xdc, 0xb3, 0xfa, 0x86, 0x85, 0x75, 0xf0, 0xfb, 0xac,
+ 0xaf, 0x42, 0x99, 0x39, 0x24, 0xec, 0x69, 0x03, 0x7e, 0x62,
+ 0xa1, 0x88, 0xbe, 0xbe, 0x30, 0xcf, 0xa1, 0xf5, 0x24, 0x9c,
+ 0xc3, 0xa5, 0xa0, 0x5d, 0x56, 0x46, 0x12, 0xb7, 0x15, 0x44,
+ 0x24, 0xa3, 0x6b, 0x0f, 0x25, 0x4b, 0x60, 0xdd, 0x62, 0xcf,
+ 0xdf, 0x0c, 0xb3, 0xc2, 0x2a, 0x2f, 0x5d, 0x62, 0xf1, 0x0f,
+ 0xdb, 0xd2, 0x56, 0x08, 0x5a, 0x59, 0x5b, 0x51, 0xbc, 0x46,
+ 0x12, 0xf3, 0xe4, 0xc0, 0x9f, 0xb3, 0xf1, 0xdc, 0x1d, 0x4c,
+ 0x93, 0xf4, 0x7d, 0xeb, 0x92, 0x6b, 0xf2, 0x12, 0x08, 0x55,
+ 0x2c, 0x37, 0xa1, 0x22, 0x24, 0x29, 0xcb, 0xfd, 0x95, 0xa6,
+ 0x4a, 0xaf, 0xfa, 0xf7, 0x0e, 0x1f, 0xc1, 0x40, 0x1b, 0x90,
+ 0x50, 0x9d, 0xeb, 0xd5, 0xdf, 0x21, 0xf9, 0x20 },
+ { 0x44, 0x8d, 0x3d, 0x72, 0xab, 0xfb, 0x9f, 0x2e, 0x2a, 0x7c,
+ 0xa4, 0xa9, 0x4d, 0x00, 0x5d, 0xda, 0x6d, 0xc7, 0x85, 0x05,
+ 0x6c, 0x05, 0x0a, 0x74, 0x92, 0xd7, 0x0a, 0x9f, 0x54, 0xba,
+ 0x14, 0xce, 0xca, 0xd0, 0x3b, 0xe7, 0xc0, 0x58, 0xfa, 0x80,
+ 0x1d, 0xc0, 0x77, 0x55, 0x29, 0xaa, 0x26, 0x5d, 0x43, 0x4d,
+ 0x09, 0xb9, 0x81, 0x97, 0xbe, 0x85, 0x7a, 0xf2, 0xd3, 0x5f,
+ 0x98, 0x58, 0xfa, 0x48, 0xf1, 0x78, 0x9c, 0x69, 0x6e, 0xd1,
+ 0xa9, 0xc3, 0x01, 0xbc, 0x30, 0x05, 0x7b, 0xb1, 0xd0, 0x00,
+ 0x6e, 0x21, 0xd5, 0x8f, 0xd3, 0x14, 0x12, 0xb8, 0x95, 0x45,
+ 0xa6, 0xaa, 0x51, 0xdc, 0x5a, 0x74, 0xca, 0x53, 0x19, 0x19,
+ 0xef, 0x3d, 0x8e, 0x00, 0x20, 0x37, 0x57, 0xac, 0x7e, 0x50,
+ 0xfc, 0x17, 0xbb, 0xa6, 0xf1, 0x36, 0x00, 0x63, 0x26, 0xe1,
+ 0xec, 0xec, 0x63, 0x3a, 0xba, 0x19, 0x24, 0xf9 },
+ { 0x76, 0x88, 0x14, 0x79, 0xcb, 0x70, 0x19, 0xa5, 0x72, 0x49,
+ 0x71, 0x75, 0xd9, 0x2a, 0x30, 0x9f, 0x28, 0x5a, 0x33, 0xdf,
+ 0x99, 0x63, 0xc4, 0x59, 0x4d, 0x8c, 0x5d, 0x67, 0x25, 0x92,
+ 0x8c, 0x78, 0x20, 0x81, 0x78, 0xec, 0x96, 0xf2, 0xfd, 0x89,
+ 0x3d, 0xcd, 0x13, 0x1f, 0xb4, 0x6f, 0x7c, 0xbc, 0xb8, 0x25,
+ 0xb1, 0x62, 0xd0, 0xe2, 0xf3, 0x37, 0x40, 0x2e, 0xf5, 0x84,
+ 0xe5, 0x48, 0x44, 0xc9, 0x10, 0x8a, 0x28, 0xb8, 0xf6, 0xa4,
+ 0x47, 0x0a, 0x0c, 0x61, 0xec, 0x99, 0x56, 0x66, 0xef, 0xdf,
+ 0xd3, 0xaa, 0xc7, 0x15, 0xa5, 0x0e, 0xaa, 0x91, 0x13, 0xad,
+ 0xe4, 0xec, 0x5f, 0xf6, 0xe4, 0xa3, 0x95, 0x5c, 0xe4, 0x2a,
+ 0x3c, 0xd9, 0xf3, 0x3b, 0xb3, 0xf4, 0x56, 0x13, 0x4b, 0x07,
+ 0x44, 0x14, 0x86, 0x83, 0x51, 0xbc, 0xa9, 0xae, 0x81, 0x5a,
+ 0xdc, 0x56, 0xf1, 0x45, 0x29, 0xb3, 0x39, 0x89 },
+ { 0x67, 0x0e, 0xb0, 0x1c, 0x5e, 0x5a, 0x86, 0x26, 0xf3, 0x76,
+ 0x00, 0xfb, 0x53, 0x2c, 0xe1, 0x80, 0x67, 0x13, 0x52, 0x60,
+ 0x59, 0xfa, 0xe5, 0x06, 0x50, 0xb9, 0xd0, 0x6e, 0xdd, 0xab,
+ 0xed, 0x19, 0xa4, 0x79, 0x24, 0x1c, 0x9f, 0xff, 0x0e, 0x3a,
+ 0xde, 0x25, 0x3f, 0x4c, 0x56, 0xcc, 0xe8, 0x15, 0xc3, 0x59,
+ 0x25, 0xd0, 0x4b, 0x18, 0x69, 0x2d, 0x17, 0x91, 0x4e, 0x1d,
+ 0xb0, 0xb7, 0x12, 0xa7, 0x1c, 0xff, 0x0e, 0xe7, 0xd0, 0x8a,
+ 0x26, 0x5d, 0x75, 0xb8, 0xd5, 0x75, 0x8b, 0xf2, 0xe1, 0xd7,
+ 0x4b, 0xc0, 0x62, 0x64, 0xa0, 0xb2, 0xae, 0xe5, 0xc2, 0xc5,
+ 0x63, 0xb4, 0x4a, 0x9e, 0xad, 0x62, 0x63, 0x60, 0x44, 0x21,
+ 0x2a, 0x33, 0x54, 0x15, 0xe8, 0xa2, 0x2c, 0xe0, 0x03, 0xa5,
+ 0xe2, 0x1a, 0x5e, 0x11, 0xb9, 0xad, 0x92, 0xbf, 0x65, 0xdb,
+ 0xba, 0x43, 0xa1, 0x14, 0x91, 0x76, 0x7e, 0xed },
+ { 0x50, 0x48, 0x52, 0xe7, 0x63, 0x5d, 0xff, 0x27, 0xb7, 0x7f,
+ 0x03, 0x66, 0x00, 0x75, 0x16, 0x6a, 0x2d, 0x0f, 0x2f, 0x98,
+ 0x1c, 0xba, 0xae, 0x32, 0x1f, 0xa9, 0xc8, 0xf5, 0x91, 0x12,
+ 0xf7, 0xd6, 0x2e, 0xe9, 0xcc, 0x15, 0x4b, 0xb9, 0x0b, 0x1f,
+ 0x23, 0x55, 0x29, 0x32, 0x7f, 0x4b, 0x79, 0x6b, 0x7b, 0x82,
+ 0x12, 0x50, 0xdb, 0x23, 0x45, 0xe9, 0x80, 0x93, 0x89, 0x9e,
+ 0x5d, 0x64, 0xee, 0xce, 0x7d, 0x93, 0x23, 0x40, 0x97, 0x5a,
+ 0x46, 0xf0, 0xa6, 0x9e, 0x94, 0x30, 0xb5, 0xe4, 0xb4, 0x76,
+ 0xfc, 0x3b, 0x3b, 0x4e, 0x7c, 0x2d, 0x13, 0x22, 0x43, 0x52,
+ 0xf3, 0x8d, 0xbe, 0xac, 0x7e, 0xff, 0x69, 0xa1, 0x04, 0xf2,
+ 0x92, 0x24, 0xdd, 0xf1, 0x91, 0x78, 0x05, 0x41, 0x2a, 0x1a,
+ 0x38, 0x45, 0xcf, 0x08, 0xec, 0xc5, 0x7f, 0x24, 0x31, 0xad,
+ 0xdf, 0x73, 0xc0, 0xaf, 0x73, 0xcd, 0xbb, 0x43 },
+ { 0x99, 0x2f, 0xe1, 0x51, 0xf7, 0xe9, 0x0c, 0xc4, 0xfb, 0x24,
+ 0xdc, 0x40, 0x52, 0x40, 0xf8, 0xb0, 0x50, 0xd0, 0xce, 0xe7,
+ 0x61, 0x8c, 0xe6, 0xc4, 0x3f, 0x4c, 0x9a, 0x19, 0xb9, 0x1e,
+ 0xae, 0x9c, 0x2f, 0x3a, 0x73, 0x08, 0xe9, 0xa9, 0xe1, 0x3f,
+ 0xd0, 0x5e, 0xf6, 0x9b, 0xe8, 0x66, 0x7d, 0x30, 0xab, 0xff,
+ 0xd9, 0xfc, 0xa9, 0xc7, 0xde, 0xb9, 0xa0, 0x53, 0x00, 0x02,
+ 0x05, 0x8b, 0x31, 0x77, 0x8a, 0x31, 0xb1, 0x2a, 0x1f, 0xab,
+ 0xf0, 0x27, 0x77, 0x35, 0x14, 0x0e, 0xd3, 0xc4, 0x29, 0xa0,
+ 0xc6, 0x6f, 0xd6, 0x17, 0x38, 0x53, 0xaf, 0x38, 0x71, 0x30,
+ 0x5c, 0x24, 0x2d, 0x95, 0x09, 0x08, 0xb0, 0x1b, 0x16, 0xd3,
+ 0xcb, 0xe8, 0xe9, 0x93, 0xad, 0x01, 0xde, 0x92, 0x84, 0xba,
+ 0xaa, 0xf6, 0x32, 0x6c, 0x07, 0x6a, 0xec, 0x6c, 0x90, 0x78,
+ 0x2f, 0x0f, 0x3c, 0xe5, 0xa2, 0xf3, 0x92, 0xfa },
+ { 0x5a, 0x68, 0xbf, 0xa8, 0x4c, 0x5b, 0x71, 0xe0, 0x13, 0x4e,
+ 0xcf, 0x4b, 0x9c, 0x8e, 0xb9, 0xfb, 0x1d, 0xc8, 0x16, 0x8a,
+ 0x99, 0x2b, 0xcc, 0x2a, 0xca, 0x92, 0xe4, 0x84, 0x9b, 0x60,
+ 0x82, 0xa9, 0x73, 0x21, 0xbe, 0xb9, 0xa2, 0xb0, 0xab, 0xd2,
+ 0x6e, 0xea, 0x5e, 0x98, 0x38, 0xa5, 0xe3, 0x3d, 0x62, 0x6e,
+ 0xe7, 0x5f, 0xc4, 0x41, 0x32, 0x5c, 0xc4, 0x45, 0x1e, 0x9c,
+ 0xef, 0x10, 0x35, 0x50, 0xa9, 0xbe, 0x08, 0x0a, 0xcd, 0x50,
+ 0xe9, 0x6b, 0xba, 0x5b, 0xb4, 0xa8, 0x47, 0x47, 0x55, 0x73,
+ 0x20, 0xb8, 0x4f, 0xa8, 0x48, 0x0c, 0xb3, 0xae, 0xe3, 0x8c,
+ 0xb0, 0x9f, 0xdd, 0x98, 0xef, 0xec, 0x98, 0x21, 0xe1, 0xae,
+ 0xa3, 0x1e, 0x48, 0xc6, 0x97, 0xb4, 0x27, 0xb0, 0x44, 0xf0,
+ 0xa8, 0x28, 0xa4, 0xde, 0xd6, 0x9d, 0x87, 0x87, 0x2f, 0x98,
+ 0x44, 0x54, 0xdb, 0x31, 0x38, 0xf1, 0x97, 0xaa },
+ { 0x78, 0xac, 0xfd, 0xf9, 0x9f, 0x5e, 0xf4, 0x39, 0x56, 0xce,
+ 0x6e, 0xf7, 0xbe, 0xf1, 0x62, 0x8f, 0xd1, 0x5c, 0x8f, 0xa0,
+ 0xa6, 0x33, 0x7b, 0x7c, 0x4b, 0xc2, 0x4a, 0x46, 0x08, 0x5a,
+ 0xd5, 0xe7, 0xeb, 0x40, 0xb0, 0x45, 0x81, 0x89, 0x7b, 0xc1,
+ 0xff, 0x98, 0x2e, 0x0a, 0x0d, 0x5c, 0xa5, 0x77, 0x71, 0xe0,
+ 0xdc, 0x98, 0x40, 0x11, 0xa3, 0x96, 0x91, 0xca, 0x1e, 0x3a,
+ 0xb8, 0xcb, 0xbb, 0xec, 0x6a, 0xb3, 0x63, 0xa8, 0x50, 0x9b,
+ 0xef, 0x61, 0x48, 0x71, 0x54, 0x8a, 0xe2, 0x41, 0x8f, 0x2e,
+ 0x6a, 0x22, 0xf4, 0x93, 0xf4, 0xdb, 0x3c, 0x0e, 0x2f, 0x5a,
+ 0x24, 0x53, 0x02, 0x6d, 0x39, 0x17, 0xed, 0x16, 0x86, 0x5b,
+ 0x0d, 0x3b, 0x9d, 0x04, 0x14, 0xde, 0x58, 0x85, 0x5b, 0x1c,
+ 0x0c, 0x26, 0xd1, 0x05, 0xff, 0xf9, 0x55, 0x02, 0xf8, 0xb0,
+ 0xb4, 0xff, 0x3b, 0x45, 0xff, 0x0a, 0x2b, 0xfb },
+ { 0x0a, 0xd9, 0x2d, 0x73, 0xd0, 0x75, 0xa3, 0x66, 0x8c, 0xb4,
+ 0xb4, 0x8c, 0xb0, 0x61, 0xc9, 0x49, 0x6f, 0x10, 0xae, 0x0f,
+ 0x90, 0x8b, 0x4a, 0x29, 0x66, 0xbc, 0xb8, 0xf0, 0x8b, 0xaa,
+ 0x6e, 0xd2, 0xf2, 0x5c, 0x93, 0xf6, 0x90, 0xae, 0x48, 0x90,
+ 0x2d, 0xfc, 0x53, 0x32, 0x37, 0xde, 0x86, 0x1f, 0xe8, 0xda,
+ 0x25, 0x3c, 0xbf, 0x31, 0xbe, 0x71, 0x98, 0x62, 0xbb, 0x76,
+ 0xa0, 0x41, 0x23, 0x1a, 0x53, 0x81, 0x52, 0x18, 0xb8, 0x3a,
+ 0x58, 0xe0, 0xe2, 0x30, 0x6e, 0xa0, 0xae, 0x36, 0xb6, 0xf7,
+ 0xde, 0x76, 0xa1, 0x24, 0x05, 0xe9, 0xf1, 0x23, 0xcd, 0x93,
+ 0x39, 0x29, 0x48, 0x14, 0xcc, 0x52, 0xd2, 0xd6, 0x02, 0x67,
+ 0x1f, 0x4a, 0x34, 0x87, 0x39, 0xed, 0xc6, 0xb9, 0xdf, 0xa2,
+ 0x2e, 0x1b, 0x95, 0x42, 0x02, 0xa0, 0xc7, 0x7f, 0x61, 0xc4,
+ 0x45, 0xbf, 0x7f, 0x15, 0xf8, 0x52, 0x01, 0x89 },
+ { 0x95, 0xbb, 0xd8, 0xa0, 0x70, 0xa6, 0xe9, 0xae, 0x8e, 0xf4,
+ 0xdc, 0xaf, 0x07, 0x5b, 0x3c, 0xed, 0x1a, 0x4f, 0xe9, 0x34,
+ 0x27, 0x9a, 0xa6, 0x6b, 0x1b, 0x78, 0xb4, 0xba, 0x0b, 0x50,
+ 0xa9, 0xeb, 0x5e, 0xbf, 0x80, 0xb7, 0x94, 0xb9, 0x0b, 0xcf,
+ 0x08, 0xfa, 0x64, 0xd3, 0x46, 0x42, 0x10, 0x97, 0xdc, 0x2a,
+ 0xc1, 0x7b, 0xa3, 0xd7, 0xd8, 0x8f, 0xec, 0x1c, 0xcf, 0xd1,
+ 0x98, 0xc3, 0x11, 0x63, 0x9a, 0xdc, 0x51, 0x51, 0xb3, 0xae,
+ 0xd5, 0xf6, 0x3e, 0xf2, 0xcb, 0x4d, 0x4a, 0xeb, 0x7f, 0xe8,
+ 0xf2, 0x2a, 0x8f, 0x4b, 0x02, 0xf4, 0x01, 0x61, 0x84, 0x7b,
+ 0x79, 0x95, 0x13, 0xe6, 0x81, 0xed, 0xea, 0x3b, 0xe0, 0x93,
+ 0xd4, 0xbe, 0x89, 0x02, 0xbe, 0x99, 0x15, 0x4b, 0x34, 0x66,
+ 0xc2, 0x80, 0x47, 0x78, 0xc6, 0x20, 0x80, 0xcd, 0x89, 0xab,
+ 0xbf, 0xb9, 0x5f, 0xed, 0xc2, 0xca, 0x54, 0x8a },
+ { 0x37, 0x5a, 0x88, 0x4f, 0xc1, 0x25, 0xa9, 0x19, 0x48, 0x0d,
+ 0xc6, 0x6f, 0xb8, 0x86, 0x7a, 0x2a, 0xad, 0x14, 0x70, 0x59,
+ 0xf2, 0x0d, 0xfc, 0xf5, 0xa0, 0xa1, 0x0d, 0x6d, 0xdf, 0xb9,
+ 0xcf, 0x21, 0xe2, 0x9f, 0xb0, 0x60, 0x2a, 0xeb, 0xe4, 0x87,
+ 0xab, 0x1d, 0x86, 0xb7, 0x2a, 0x35, 0x94, 0x7f, 0x89, 0x30,
+ 0x53, 0xfc, 0xc0, 0x55, 0x4e, 0xc1, 0x69, 0xff, 0x35, 0xea,
+ 0x51, 0x4f, 0x5c, 0x04, 0xca, 0xc1, 0xe5, 0xd0, 0xbd, 0x07,
+ 0xd9, 0x0f, 0xfa, 0x42, 0x9c, 0x71, 0xe2, 0xf0, 0xe3, 0x89,
+ 0x07, 0x2b, 0xaa, 0x63, 0x5c, 0x16, 0xd3, 0x36, 0x31, 0x4e,
+ 0xf4, 0xe0, 0xaa, 0xde, 0x06, 0x6a, 0x2b, 0xfa, 0xaf, 0x47,
+ 0x8e, 0x83, 0x5c, 0x42, 0xe2, 0x47, 0xc9, 0xec, 0xfc, 0x1b,
+ 0xd6, 0xa7, 0x75, 0x67, 0xa8, 0x87, 0xb8, 0x23, 0xe3, 0x63,
+ 0x59, 0xf9, 0x24, 0x95, 0xe6, 0x14, 0xbb, 0xd0 },
+ { 0x26, 0x8d, 0x81, 0x8b, 0x08, 0xcb, 0x84, 0xec, 0x66, 0xbb,
+ 0x09, 0x3b, 0x38, 0x41, 0x53, 0x79, 0x9f, 0xe0, 0xdd, 0xa7,
+ 0x19, 0x68, 0x83, 0x8a, 0x01, 0xcd, 0xcd, 0xe2, 0x4f, 0xd1,
+ 0x2a, 0xdb, 0xde, 0xc7, 0x5c, 0x81, 0xaf, 0xa6, 0x3c, 0x55,
+ 0xc7, 0x30, 0x3c, 0x80, 0x1e, 0xaa, 0x8c, 0x47, 0x26, 0xaa,
+ 0x69, 0xea, 0x60, 0x79, 0xc9, 0xa0, 0xfd, 0x97, 0xfb, 0xb0,
+ 0xb9, 0x1a, 0x67, 0x63, 0xfd, 0xf3, 0x67, 0x63, 0x54, 0x1e,
+ 0x06, 0x67, 0xb9, 0x3e, 0xd9, 0xc9, 0x2f, 0x1c, 0x59, 0x50,
+ 0x40, 0x32, 0x5f, 0x99, 0xc8, 0xd3, 0x06, 0x68, 0xba, 0xeb,
+ 0xc6, 0x64, 0xd1, 0x3a, 0x0d, 0x86, 0x67, 0x88, 0x64, 0xa0,
+ 0xe4, 0xfd, 0x73, 0xca, 0xf7, 0x70, 0x7e, 0xc0, 0x1b, 0xdb,
+ 0x1a, 0x54, 0x1a, 0x16, 0x1e, 0x2a, 0x87, 0x5c, 0x6d, 0xab,
+ 0x17, 0x8c, 0xbe, 0x2e, 0x12, 0x17, 0xf7, 0xea },
+ { 0x8b, 0x02, 0x73, 0x5c, 0x05, 0x6c, 0xa4, 0x4b, 0x84, 0x19,
+ 0xed, 0x4b, 0x01, 0xb5, 0x3a, 0x56, 0x3e, 0xb9, 0x3b, 0x33,
+ 0x4f, 0x5f, 0x2b, 0xf5, 0x11, 0x71, 0xfe, 0x3c, 0x44, 0x35,
+ 0x51, 0x6a, 0xe2, 0x4c, 0x02, 0x8a, 0x2e, 0x7a, 0x20, 0x8e,
+ 0x81, 0x6b, 0x63, 0x3a, 0x0f, 0x97, 0x91, 0x89, 0x88, 0x3f,
+ 0xad, 0x37, 0xbd, 0x70, 0x7c, 0x2e, 0xa5, 0xe7, 0x7e, 0xed,
+ 0x3a, 0x7d, 0x83, 0x75, 0x86, 0xef, 0x4e, 0xdb, 0x33, 0x9e,
+ 0x4a, 0x78, 0x7f, 0x7d, 0x31, 0x64, 0x2b, 0x72, 0x01, 0x40,
+ 0xb5, 0xae, 0x04, 0xe4, 0x64, 0x38, 0xd7, 0xee, 0x37, 0xb0,
+ 0xcb, 0x5b, 0x9f, 0xa8, 0xe0, 0x66, 0xda, 0x40, 0x99, 0xf2,
+ 0xb2, 0x4e, 0xe9, 0xde, 0x24, 0x0c, 0x10, 0x13, 0xbe, 0xcc,
+ 0xc1, 0xab, 0x4f, 0xc3, 0x2e, 0x67, 0x47, 0x3d, 0x10, 0x3b,
+ 0x73, 0xda, 0xe3, 0x58, 0x41, 0x58, 0x05, 0x55 },
+ { 0x40, 0x0e, 0x3a, 0xa0, 0x4b, 0x4d, 0x85, 0xfe, 0x5a, 0xb4,
+ 0x5c, 0x3f, 0x04, 0x36, 0x50, 0x42, 0x58, 0x22, 0xa7, 0x82,
+ 0xfd, 0x35, 0x40, 0xd8, 0xb3, 0x2e, 0xcf, 0x7e, 0x58, 0x77,
+ 0x3d, 0x4c, 0xf5, 0x71, 0xff, 0xdb, 0xc3, 0x00, 0x6c, 0x0d,
+ 0xd1, 0xf0, 0x02, 0x4c, 0x8a, 0x0c, 0x81, 0x82, 0x3e, 0x14,
+ 0x9a, 0xf9, 0x5e, 0x98, 0x97, 0x34, 0x16, 0x7d, 0x82, 0x81,
+ 0xd7, 0xe3, 0xad, 0x1b, 0xba, 0xe6, 0xc7, 0xfe, 0x8e, 0x1b,
+ 0x76, 0xc2, 0xd9, 0x55, 0x2d, 0x19, 0xaf, 0xbc, 0xe2, 0x65,
+ 0x97, 0xc6, 0x76, 0x8e, 0xe6, 0x49, 0x1f, 0xfe, 0x48, 0x5d,
+ 0x7a, 0xb4, 0x0d, 0x99, 0x5b, 0xc9, 0xec, 0x71, 0xbc, 0x5a,
+ 0x91, 0xbd, 0xf9, 0x2f, 0xac, 0x12, 0x0e, 0x6e, 0x2b, 0xfc,
+ 0x3b, 0x21, 0x1d, 0xe4, 0xc0, 0x26, 0xf3, 0xfc, 0x28, 0xc1,
+ 0xb8, 0x9b, 0xb4, 0x64, 0xe1, 0x01, 0x91, 0x95 },
+ { 0x13, 0x1c, 0x3d, 0xa2, 0x8d, 0xa6, 0xe0, 0x39, 0x4a, 0x42,
+ 0xb9, 0xac, 0xf3, 0xa6, 0xa1, 0x98, 0x36, 0x2f, 0x76, 0x47,
+ 0xad, 0xaf, 0x1f, 0x4d, 0x09, 0xc1, 0x57, 0xd4, 0x4a, 0x13,
+ 0x00, 0x9b, 0xc8, 0x07, 0xc7, 0x79, 0x96, 0x71, 0x85, 0xb1,
+ 0x27, 0xc3, 0xe0, 0x32, 0x67, 0xcb, 0x58, 0x6f, 0x3e, 0xd3,
+ 0x50, 0xb9, 0xf1, 0x64, 0x51, 0xa7, 0xa3, 0xc2, 0x85, 0x06,
+ 0xc8, 0x9f, 0xc3, 0xf5, 0xfe, 0xd6, 0x60, 0xd5, 0x06, 0x21,
+ 0xa9, 0x9b, 0xff, 0x38, 0x67, 0xb8, 0xa5, 0x01, 0x22, 0x96,
+ 0x65, 0xb2, 0x2e, 0xc9, 0x73, 0xc2, 0x53, 0xdb, 0xda, 0x17,
+ 0xc4, 0x1b, 0xc5, 0x10, 0x7a, 0xb7, 0x5e, 0x13, 0xaa, 0xc3,
+ 0xe5, 0xe0, 0xac, 0x2e, 0x65, 0x92, 0x23, 0xb1, 0xc6, 0x0e,
+ 0xc7, 0x7d, 0x37, 0xa2, 0xed, 0x64, 0x24, 0x13, 0x60, 0x74,
+ 0x47, 0x32, 0x16, 0x49, 0x5e, 0x46, 0xe4, 0xa2 },
+ { 0x71, 0xd1, 0xa4, 0x6a, 0x34, 0x54, 0x5c, 0xe9, 0xde, 0x80,
+ 0x98, 0xad, 0x44, 0xaa, 0x0f, 0xf0, 0xb9, 0x20, 0xaa, 0xc1,
+ 0xb2, 0xc1, 0x76, 0x15, 0xa7, 0xc0, 0x74, 0xf1, 0x1c, 0xb0,
+ 0xe8, 0xff, 0x13, 0x15, 0x14, 0xd7, 0x5d, 0x75, 0xf1, 0x54,
+ 0x6b, 0x79, 0xcf, 0x97, 0xc4, 0xc6, 0x90, 0xc9, 0x0f, 0xf7,
+ 0x83, 0x8b, 0x9d, 0xf1, 0xe7, 0xc8, 0x06, 0x0c, 0xa4, 0xdf,
+ 0xcb, 0x02, 0xdb, 0x90, 0x60, 0xc2, 0x61, 0xaf, 0x73, 0x0e,
+ 0x83, 0xfd, 0x19, 0x8c, 0x44, 0x4b, 0xf4, 0xc2, 0x08, 0x3c,
+ 0x99, 0xbb, 0x45, 0x04, 0xcd, 0x3b, 0x2f, 0x32, 0x3d, 0x32,
+ 0xd6, 0x10, 0xfd, 0xa2, 0x51, 0xb9, 0xc5, 0x8d, 0x41, 0x1a,
+ 0x80, 0xf5, 0xf4, 0xa2, 0x7c, 0x08, 0x99, 0xbd, 0xec, 0x03,
+ 0xf8, 0x12, 0xf4, 0x15, 0xb4, 0x25, 0xd0, 0x4f, 0x44, 0x36,
+ 0x4a, 0x78, 0x5f, 0xf1, 0xa7, 0xda, 0x83, 0xba },
+ { 0x6c, 0xd2, 0x69, 0x9f, 0x11, 0x67, 0xf5, 0x21, 0xb9, 0x5c,
+ 0xc4, 0x16, 0x53, 0x3d, 0x0a, 0xcb, 0x39, 0x64, 0xff, 0x3a,
+ 0x24, 0xc5, 0x2d, 0x4b, 0x3e, 0x90, 0xd7, 0x16, 0x36, 0x48,
+ 0xfa, 0xb9, 0x00, 0x8e, 0xab, 0xdf, 0x32, 0x5f, 0xc1, 0x3a,
+ 0xd8, 0xcc, 0xf9, 0x0c, 0x17, 0xd3, 0xb6, 0xd5, 0x82, 0x4f,
+ 0xda, 0xdd, 0x5e, 0x4d, 0x60, 0xf6, 0x0f, 0x47, 0xb3, 0xa8,
+ 0x4f, 0x78, 0x54, 0x0b, 0xc3, 0xb4, 0x4a, 0x85, 0x60, 0xa4,
+ 0x56, 0x41, 0x1f, 0x65, 0xda, 0xfd, 0x6e, 0x65, 0xe3, 0xd7,
+ 0xf6, 0x37, 0xa5, 0x88, 0x79, 0x3c, 0xec, 0xcf, 0xc5, 0x41,
+ 0x0d, 0xb6, 0xca, 0x3b, 0xed, 0x06, 0x27, 0xd3, 0x8b, 0xa4,
+ 0x8d, 0x72, 0x62, 0x2c, 0xaa, 0x5a, 0xab, 0x2a, 0xc5, 0xd4,
+ 0xd1, 0x30, 0xa0, 0xd8, 0xec, 0xc3, 0x77, 0x2d, 0xda, 0x0d,
+ 0x76, 0x17, 0x8f, 0x76, 0xfa, 0x1b, 0x38, 0x2e },
+ { 0x32, 0x7c, 0x06, 0x3f, 0xda, 0x34, 0x5d, 0xc2, 0x19, 0xee,
+ 0xe2, 0x74, 0xc7, 0xee, 0xb8, 0x26, 0xfa, 0x2e, 0xfc, 0xb8,
+ 0x6c, 0x88, 0xc9, 0x65, 0xe8, 0xf0, 0x37, 0x42, 0x30, 0xab,
+ 0x19, 0x6f, 0x93, 0x38, 0xc3, 0x4d, 0xf2, 0x73, 0x55, 0x69,
+ 0x4b, 0x4b, 0x19, 0xa6, 0xc6, 0x1a, 0x04, 0xbc, 0x0d, 0xe4,
+ 0x17, 0xeb, 0xe2, 0xba, 0xc3, 0x9b, 0xd3, 0x0f, 0xe4, 0x0b,
+ 0xa5, 0x8a, 0xcb, 0xb4, 0x7b, 0xbd, 0xc7, 0x49, 0x16, 0xab,
+ 0x7b, 0x5e, 0xe1, 0x5f, 0x28, 0x2c, 0x08, 0x7a, 0xda, 0xdd,
+ 0x89, 0x27, 0x95, 0xa7, 0x58, 0x57, 0x42, 0xf2, 0xeb, 0x70,
+ 0x93, 0xd0, 0xcd, 0x8f, 0x14, 0x42, 0x22, 0xdd, 0x68, 0x93,
+ 0x7c, 0x5a, 0x8c, 0x82, 0x54, 0x00, 0x34, 0xf8, 0x30, 0xf3,
+ 0x73, 0x26, 0xb0, 0x3d, 0xcf, 0xe2, 0x99, 0xd1, 0xbd, 0xfb,
+ 0x2d, 0x8c, 0x0b, 0x3b, 0x12, 0xf4, 0xf3, 0xac },
+ { 0x02, 0x0f, 0x19, 0xd1, 0xc0, 0xdf, 0x68, 0x56, 0xeb, 0x6b,
+ 0x9d, 0x2a, 0x36, 0x70, 0x11, 0x2c, 0x9a, 0xfb, 0xa8, 0x22,
+ 0x48, 0xb0, 0x1a, 0xf2, 0x7a, 0x42, 0xa9, 0x4b, 0xda, 0x5f,
+ 0xa5, 0xbf, 0x1a, 0xf4, 0xc4, 0x96, 0x6c, 0x27, 0xb8, 0x3b,
+ 0x72, 0xaa, 0x22, 0xb2, 0xee, 0xcb, 0x4f, 0x87, 0x06, 0x23,
+ 0xa1, 0xfe, 0x39, 0xf3, 0xcd, 0x22, 0x1b, 0xe4, 0xe0, 0x59,
+ 0x93, 0xb4, 0x87, 0x80, 0x37, 0x04, 0x00, 0xf2, 0x13, 0x0b,
+ 0xfb, 0x7c, 0xd1, 0x59, 0x50, 0x9e, 0xda, 0x81, 0x33, 0x36,
+ 0xe5, 0x8d, 0xfc, 0xc8, 0x36, 0x6d, 0x6a, 0x5f, 0xc4, 0x21,
+ 0x6b, 0x79, 0x02, 0x2d, 0xe2, 0x71, 0xc3, 0xe7, 0xc2, 0xaa,
+ 0xb1, 0xc2, 0x5a, 0x16, 0xe6, 0x4e, 0xcc, 0x7b, 0x14, 0x02,
+ 0xa8, 0x66, 0xbb, 0xe9, 0x86, 0x9d, 0x19, 0x43, 0xae, 0xfe,
+ 0xab, 0x39, 0x9e, 0xff, 0x5b, 0x47, 0xcd, 0x53 },
+ { 0x79, 0xe7, 0x27, 0x20, 0xb0, 0x05, 0x05, 0x44, 0xf7, 0x57,
+ 0xe1, 0xff, 0x0c, 0x88, 0x8f, 0x60, 0x99, 0xd0, 0x90, 0xeb,
+ 0xac, 0xca, 0x11, 0x60, 0x54, 0xb0, 0x09, 0x2a, 0xf1, 0x8a,
+ 0x07, 0x70, 0x26, 0x27, 0x43, 0x86, 0x8b, 0x4f, 0x6b, 0xba,
+ 0x47, 0x69, 0x9e, 0xbe, 0x72, 0x0c, 0x3a, 0xdb, 0x91, 0x60,
+ 0x58, 0xec, 0x5b, 0x23, 0x17, 0x27, 0x5f, 0xba, 0x16, 0xd3,
+ 0xcc, 0xdd, 0xef, 0xce, 0x79, 0xfb, 0xbf, 0xd3, 0xa3, 0xd0,
+ 0x57, 0xcf, 0xe3, 0x7e, 0xe2, 0xf2, 0x4c, 0xd6, 0x11, 0x47,
+ 0x3b, 0x93, 0x7e, 0xe3, 0x3a, 0x48, 0x62, 0x68, 0xe9, 0xff,
+ 0x02, 0x3d, 0x10, 0x28, 0x5a, 0x24, 0x94, 0x40, 0x30, 0x2d,
+ 0xd2, 0xbc, 0xcc, 0x4d, 0x9a, 0x78, 0x0a, 0x19, 0xe6, 0x52,
+ 0x58, 0x40, 0xb6, 0x18, 0xeb, 0xc6, 0xdb, 0x1d, 0xe5, 0xc5,
+ 0x37, 0x05, 0x1a, 0x86, 0xa4, 0xdb, 0xba, 0x20 },
+ { 0x00, 0x1d, 0x3c, 0xe3, 0x70, 0x15, 0x84, 0x6d, 0xe4, 0x28,
+ 0xb2, 0xb5, 0x95, 0x11, 0xa0, 0x56, 0xa4, 0x48, 0x79, 0x27,
+ 0x38, 0xa1, 0x93, 0x9d, 0x37, 0xaf, 0x7f, 0x83, 0xfb, 0xd1,
+ 0x5e, 0x05, 0xe9, 0xb5, 0xbb, 0x45, 0x2a, 0x9f, 0x55, 0x8c,
+ 0x58, 0xda, 0xa7, 0x3a, 0xa1, 0x26, 0x85, 0x1c, 0x14, 0xa3,
+ 0x85, 0x4e, 0xcb, 0xc5, 0x38, 0xf9, 0x70, 0xc7, 0x9c, 0x56,
+ 0x66, 0xcd, 0xbd, 0x8d, 0xe9, 0x61, 0xaf, 0x3e, 0x77, 0x43,
+ 0xa9, 0x85, 0xf2, 0x52, 0xca, 0x0c, 0x78, 0x93, 0x75, 0xa1,
+ 0x9f, 0x29, 0xd9, 0x7b, 0xde, 0x16, 0x67, 0x6f, 0x54, 0x84,
+ 0x55, 0xa0, 0xb9, 0x80, 0x44, 0x6d, 0xd2, 0x45, 0x3c, 0x39,
+ 0x5a, 0x3e, 0xe7, 0xaa, 0xd6, 0x1f, 0xd6, 0xba, 0x48, 0xc0,
+ 0xa1, 0xdf, 0xb1, 0xa3, 0x97, 0x4e, 0xaa, 0xe6, 0xb3, 0x10,
+ 0x63, 0x2a, 0xcf, 0x25, 0x28, 0x20, 0xa2, 0x39 },
+ { 0x4b, 0xb8, 0xc6, 0xfc, 0x40, 0xaf, 0xc6, 0x84, 0xb3, 0x28,
+ 0x03, 0x60, 0x79, 0x0b, 0x7a, 0x04, 0x05, 0x75, 0x90, 0x47,
+ 0xfc, 0x58, 0x5e, 0x46, 0x07, 0x1b, 0xd5, 0xfc, 0x11, 0xd4,
+ 0x01, 0x94, 0x34, 0xcc, 0x13, 0x4a, 0xfc, 0xd2, 0xc4, 0x04,
+ 0xe7, 0x36, 0x94, 0xbc, 0xf3, 0x69, 0x3a, 0x18, 0xcc, 0x12,
+ 0xa4, 0x9d, 0x56, 0x83, 0x3e, 0xdc, 0x65, 0xed, 0x39, 0xc7,
+ 0x59, 0x4d, 0x02, 0xb3, 0xb4, 0xc8, 0x0e, 0x2f, 0xff, 0xb8,
+ 0x16, 0x5d, 0x91, 0xcd, 0xd7, 0x54, 0x75, 0x0f, 0x28, 0xe4,
+ 0xb1, 0xa1, 0xf7, 0x0b, 0x51, 0x2f, 0x79, 0x7c, 0xa5, 0xab,
+ 0x62, 0xb8, 0xd9, 0x08, 0x97, 0xb1, 0x95, 0x10, 0x44, 0xe6,
+ 0xc3, 0x43, 0xf5, 0x39, 0x2e, 0x56, 0x2e, 0x7d, 0xe7, 0xc0,
+ 0xf6, 0xdb, 0xf3, 0xe3, 0x93, 0x8a, 0x00, 0x9c, 0x56, 0x64,
+ 0xd6, 0xbe, 0x36, 0xb9, 0xe1, 0x45, 0xb1, 0xd7 },
+ { 0x36, 0x99, 0xa8, 0x81, 0xb6, 0xa7, 0x7e, 0x78, 0x2e, 0x8f,
+ 0xea, 0x9e, 0x9a, 0x13, 0x5d, 0x89, 0xd4, 0xf9, 0xcf, 0xa5,
+ 0x6c, 0x43, 0x28, 0x27, 0x99, 0xa3, 0xe8, 0x8d, 0x10, 0xff,
+ 0xa6, 0x90, 0xc0, 0x3f, 0x5d, 0xf9, 0x59, 0x12, 0x0b, 0xfc,
+ 0x56, 0x96, 0xd5, 0x45, 0x36, 0xd5, 0x05, 0x29, 0xac, 0xd1,
+ 0xd6, 0xf2, 0x70, 0x9d, 0xc5, 0x90, 0x86, 0x0c, 0x21, 0x8a,
+ 0xc8, 0x2c, 0x9c, 0x16, 0x2f, 0x12, 0x4e, 0x3b, 0x29, 0x35,
+ 0x19, 0xeb, 0xeb, 0x8a, 0xf4, 0x44, 0x01, 0x99, 0xb5, 0x3c,
+ 0x48, 0x7f, 0xe9, 0xcd, 0x9f, 0xeb, 0xc0, 0x05, 0x39, 0xe4,
+ 0xec, 0xf0, 0x8c, 0xb8, 0x14, 0x39, 0x37, 0xe5, 0xb6, 0xd6,
+ 0x60, 0x07, 0x27, 0x3b, 0xfe, 0xa3, 0x66, 0xc0, 0xa9, 0x36,
+ 0x9c, 0x6e, 0x69, 0x68, 0xa4, 0x0d, 0xb1, 0x33, 0xc9, 0xde,
+ 0x31, 0x20, 0xe2, 0xdd, 0xfd, 0x0f, 0x87, 0x96 },
+ { 0x4f, 0x3a, 0x4b, 0x03, 0x20, 0x8a, 0xff, 0x8b, 0x1d, 0xf0,
+ 0x8e, 0x9f, 0x82, 0x53, 0x51, 0x87, 0x72, 0x71, 0xf3, 0x9e,
+ 0x5e, 0xc3, 0x1c, 0xaa, 0xca, 0x94, 0x75, 0xe9, 0x78, 0x1c,
+ 0xb4, 0x73, 0xb9, 0xe0, 0x8e, 0xc0, 0x3d, 0x7a, 0x4d, 0x52,
+ 0x83, 0x8d, 0xaa, 0x54, 0xd3, 0xb7, 0xc2, 0x35, 0xee, 0x2c,
+ 0xd2, 0x0d, 0x6a, 0x8d, 0x4f, 0x9f, 0x8c, 0x23, 0xc2, 0x5f,
+ 0x14, 0x26, 0xa8, 0x0d, 0x79, 0x5e, 0xc6, 0xcb, 0xc5, 0xe6,
+ 0x7c, 0x02, 0x94, 0xdb, 0xdf, 0xe2, 0xe9, 0xac, 0x3a, 0x75,
+ 0x82, 0xc5, 0x3a, 0x7e, 0x88, 0x34, 0xe9, 0xc5, 0xcb, 0xde,
+ 0x41, 0x6e, 0x20, 0x58, 0xb3, 0x7f, 0x06, 0xc1, 0x71, 0x51,
+ 0x4f, 0x7c, 0xbf, 0x4d, 0xb7, 0xe2, 0xe9, 0xb3, 0x65, 0x37,
+ 0x10, 0x6f, 0xe9, 0xcf, 0x3a, 0x2d, 0xf1, 0xd2, 0x81, 0x54,
+ 0x5b, 0xca, 0x33, 0x72, 0x1e, 0xb1, 0xc6, 0x4d },
+ { 0x6d, 0x87, 0x44, 0x46, 0xa6, 0xd1, 0x79, 0xfd, 0x9e, 0x52,
+ 0x5c, 0x03, 0x0b, 0x5a, 0x7b, 0x80, 0x44, 0xf2, 0x4f, 0x4a,
+ 0x52, 0xae, 0x84, 0xdb, 0x49, 0xbe, 0x1c, 0x18, 0x7a, 0x02,
+ 0x32, 0x5e, 0x13, 0x15, 0x2b, 0x3e, 0xb0, 0x20, 0x60, 0x7a,
+ 0x56, 0xd7, 0x14, 0xab, 0xd1, 0x04, 0x9d, 0xf4, 0xc4, 0x3d,
+ 0x54, 0xfa, 0x5a, 0xc4, 0x88, 0xaa, 0x9f, 0x53, 0x59, 0xfd,
+ 0xdf, 0x86, 0xe0, 0xa2, 0xf9, 0x60, 0x38, 0x68, 0x6d, 0xf2,
+ 0x0d, 0x7c, 0xb4, 0xec, 0xd5, 0xdb, 0xd7, 0x2b, 0x21, 0xc1,
+ 0x24, 0x54, 0xbb, 0x9c, 0x42, 0x1e, 0xec, 0x37, 0xb9, 0x63,
+ 0x4a, 0x97, 0xe3, 0xe0, 0xf1, 0x6e, 0xb1, 0x14, 0x63, 0x4e,
+ 0x07, 0xd8, 0xe3, 0x11, 0x8b, 0x0f, 0x98, 0x52, 0xaf, 0xb3,
+ 0x6d, 0x1d, 0x23, 0xe3, 0x7f, 0xa6, 0xda, 0x22, 0x6d, 0x4e,
+ 0x0f, 0x7b, 0x81, 0x07, 0x1e, 0xd0, 0x95, 0xf8 },
+ { 0x3c, 0xf3, 0x84, 0xc9, 0xff, 0x9c, 0x56, 0x09, 0x95, 0xa4,
+ 0xac, 0xa9, 0x7b, 0xb7, 0x0f, 0x3d, 0x95, 0xa3, 0x97, 0x34,
+ 0x90, 0x4f, 0xc5, 0x31, 0x17, 0xf5, 0x14, 0xad, 0x07, 0xac,
+ 0x75, 0x9d, 0x0f, 0x5d, 0x79, 0x1f, 0xaf, 0x08, 0x48, 0xbc,
+ 0x5c, 0xaa, 0xc2, 0x70, 0x7d, 0xeb, 0x85, 0x80, 0xa0, 0xed,
+ 0xc4, 0xa7, 0x42, 0xc1, 0xd2, 0x13, 0xe0, 0x3f, 0x1f, 0x34,
+ 0xf3, 0xfd, 0x3b, 0x74, 0x6e, 0x1a, 0x0f, 0x01, 0xf5, 0x7f,
+ 0x7c, 0xeb, 0x27, 0xfb, 0xa8, 0x76, 0xcf, 0x28, 0xcc, 0xc2,
+ 0x05, 0xf6, 0xdf, 0x92, 0x31, 0xae, 0x94, 0xe4, 0x99, 0xc2,
+ 0xb4, 0xdc, 0xf8, 0xd4, 0x4f, 0x12, 0x4e, 0x19, 0xe0, 0xdf,
+ 0x88, 0xfe, 0xe9, 0x1a, 0x71, 0xa7, 0x5a, 0x6d, 0x9d, 0xc6,
+ 0x9e, 0xa1, 0x1f, 0xd5, 0x31, 0x6c, 0x37, 0x81, 0xcc, 0xc8,
+ 0xd2, 0x9d, 0x07, 0xaa, 0xbe, 0x9a, 0x42, 0xf5 },
+ { 0x2b, 0x24, 0x88, 0x50, 0xee, 0x73, 0xdf, 0x26, 0x3c, 0x67,
+ 0xe7, 0x3c, 0x71, 0x03, 0x07, 0x70, 0x8c, 0x8c, 0x54, 0x05,
+ 0xd8, 0x56, 0x0a, 0x65, 0x26, 0x48, 0x28, 0xd9, 0xd4, 0x55,
+ 0xe8, 0x20, 0x85, 0x52, 0x5d, 0x65, 0xbe, 0x99, 0xa6, 0x08,
+ 0x09, 0x98, 0x06, 0xbb, 0x74, 0x7e, 0x5d, 0x2a, 0xf4, 0xd9,
+ 0x7a, 0xfb, 0x14, 0x83, 0x21, 0xbd, 0xf3, 0x80, 0xfc, 0xb5,
+ 0x05, 0xe4, 0x51, 0xe9, 0x51, 0x17, 0x4e, 0x1a, 0x57, 0x7b,
+ 0x24, 0xf4, 0xb6, 0xc5, 0xd9, 0x91, 0x62, 0x93, 0x62, 0xe1,
+ 0x1e, 0xf3, 0x39, 0xb7, 0xfe, 0x24, 0xf3, 0x9a, 0x90, 0x58,
+ 0x0b, 0x90, 0xce, 0x26, 0xa8, 0xe1, 0xca, 0x86, 0x02, 0xa8,
+ 0x79, 0xb2, 0x09, 0xf7, 0x2b, 0x4a, 0x1b, 0x8d, 0xe7, 0x2b,
+ 0xf7, 0xb3, 0x49, 0x72, 0x17, 0x42, 0x67, 0x6b, 0x03, 0x99,
+ 0x70, 0x05, 0x06, 0xba, 0xce, 0x1f, 0xc9, 0xe3 },
+ { 0x93, 0x8b, 0x3b, 0xcc, 0x6a, 0x3a, 0xc2, 0x15, 0x17, 0x26,
+ 0x1e, 0xce, 0x74, 0x41, 0x4a, 0x1c, 0xa1, 0x08, 0xb5, 0x4d,
+ 0x1d, 0x46, 0x21, 0xd1, 0x52, 0x48, 0x67, 0x58, 0xe8, 0x1b,
+ 0x0d, 0xf0, 0xac, 0x07, 0xf2, 0xa3, 0x73, 0xce, 0x49, 0xe8,
+ 0xb2, 0xf9, 0xd4, 0x41, 0xc1, 0x26, 0xbc, 0xbe, 0x63, 0x48,
+ 0xf7, 0xf2, 0xe6, 0x6c, 0x66, 0xf6, 0x4b, 0x90, 0x36, 0x3d,
+ 0x74, 0xc6, 0x69, 0x75, 0x12, 0x48, 0xc5, 0x8f, 0x62, 0xd8,
+ 0x43, 0xb9, 0x6c, 0x56, 0xb8, 0xef, 0x81, 0x0f, 0xcc, 0x6c,
+ 0xdb, 0x0e, 0x58, 0x7c, 0xb5, 0xed, 0x29, 0x45, 0x07, 0x1a,
+ 0x02, 0x10, 0xa6, 0xb2, 0x34, 0x4a, 0x52, 0xc2, 0x07, 0xd6,
+ 0xa8, 0xb2, 0x3e, 0x40, 0x07, 0xa2, 0x86, 0x19, 0x1f, 0x2c,
+ 0xa1, 0xc7, 0x78, 0x22, 0x4c, 0x18, 0x4f, 0xb4, 0x10, 0xb2,
+ 0x21, 0x73, 0xcd, 0xe6, 0x85, 0x41, 0x15, 0x9f },
+ { 0x6c, 0xff, 0x58, 0xa5, 0xd9, 0xe8, 0x9d, 0x6b, 0x24, 0xe8,
+ 0xc9, 0xed, 0x15, 0x30, 0x73, 0x41, 0x98, 0x47, 0x46, 0x07,
+ 0x84, 0xe8, 0x3c, 0x06, 0x8a, 0xe7, 0xe0, 0xe8, 0xf2, 0xda,
+ 0xce, 0x56, 0x79, 0x70, 0x17, 0x9b, 0x93, 0x74, 0x7e, 0xa5,
+ 0x60, 0xf7, 0xa1, 0xb5, 0xa5, 0x5b, 0x44, 0xb7, 0xae, 0x46,
+ 0x55, 0xe5, 0x74, 0xd6, 0xeb, 0x5f, 0xb5, 0x66, 0xb7, 0x90,
+ 0x92, 0x53, 0x3d, 0x97, 0x74, 0x02, 0x05, 0x76, 0x56, 0xf7,
+ 0x6d, 0x5f, 0x81, 0x8c, 0x2a, 0xec, 0xf5, 0x54, 0x2d, 0xf5,
+ 0xe6, 0x0f, 0xb6, 0x1a, 0xda, 0x0b, 0xb6, 0x4c, 0xf3, 0x04,
+ 0xfc, 0x58, 0x49, 0x10, 0x1b, 0x06, 0x1c, 0x3a, 0x04, 0x34,
+ 0xaa, 0xa6, 0x57, 0xa9, 0x97, 0x08, 0x96, 0x06, 0xdc, 0xd7,
+ 0x3a, 0xcb, 0x8e, 0x65, 0xfb, 0x2a, 0x80, 0xe8, 0x80, 0x36,
+ 0xa9, 0xe4, 0xa1, 0x6b, 0xe4, 0xde, 0xd3, 0x40 },
+ { 0x5f, 0xe4, 0xac, 0x8f, 0x31, 0xb7, 0x93, 0x27, 0x5f, 0x67,
+ 0xf8, 0xaa, 0xeb, 0x93, 0x6a, 0xf7, 0x3c, 0x62, 0x7f, 0xc5,
+ 0x48, 0x63, 0xb3, 0xac, 0xc3, 0x3f, 0x83, 0xd8, 0x04, 0x6e,
+ 0x2e, 0x48, 0x7f, 0xa8, 0x47, 0xe6, 0x6e, 0xc1, 0x3f, 0x84,
+ 0x13, 0x3d, 0x54, 0x44, 0xcc, 0xc8, 0xc7, 0xdf, 0xb1, 0xd4,
+ 0x04, 0xdc, 0x38, 0xd3, 0x17, 0xe0, 0x0b, 0x68, 0x0b, 0x0a,
+ 0xff, 0x18, 0x20, 0xb8, 0xfb, 0xbb, 0x2f, 0xa6, 0xd0, 0x23,
+ 0x3f, 0xdc, 0x35, 0x00, 0x10, 0x13, 0x80, 0x9f, 0x50, 0xf4,
+ 0x05, 0x5c, 0x3b, 0x1e, 0x9b, 0x45, 0x38, 0x96, 0xd1, 0x48,
+ 0x46, 0x7d, 0x60, 0x7d, 0x97, 0x98, 0x25, 0x5e, 0x90, 0x7a,
+ 0x03, 0xe4, 0x15, 0xb7, 0xf7, 0x99, 0x8d, 0x0b, 0x09, 0xbd,
+ 0x88, 0x05, 0xe1, 0xd1, 0xf2, 0x25, 0x1d, 0x2f, 0xe7, 0xd6,
+ 0x50, 0x8c, 0x01, 0xb0, 0x03, 0xe5, 0x1f, 0x68 },
+ { 0x81, 0x37, 0x71, 0x64, 0x12, 0x1c, 0x05, 0x48, 0x20, 0x93,
+ 0x1c, 0x89, 0xeb, 0x2a, 0xbd, 0xad, 0x86, 0xe2, 0x54, 0xc9,
+ 0x69, 0x77, 0xa4, 0x20, 0x29, 0x0d, 0x95, 0xf2, 0x20, 0x10,
+ 0xf2, 0xe7, 0x8d, 0xcc, 0x0c, 0x42, 0x49, 0xa2, 0x78, 0x64,
+ 0x69, 0xc9, 0xcf, 0xb0, 0xb1, 0x84, 0xce, 0xe8, 0xdd, 0x8d,
+ 0xec, 0x2b, 0x34, 0xe7, 0xe7, 0x12, 0x55, 0xc3, 0x85, 0x93,
+ 0x00, 0xbb, 0x42, 0xdc, 0xba, 0xfc, 0x1d, 0x34, 0x6b, 0x83,
+ 0xe9, 0x5c, 0x18, 0x63, 0x7c, 0x7c, 0x7f, 0xef, 0x96, 0xd0,
+ 0x06, 0x6c, 0x55, 0xfb, 0x99, 0xa4, 0x6e, 0xaf, 0x54, 0x54,
+ 0xa7, 0xd4, 0x69, 0x37, 0x1c, 0x95, 0xfd, 0xd1, 0x1f, 0x04,
+ 0x9c, 0x22, 0xbc, 0xd4, 0x7b, 0x01, 0x87, 0x26, 0x6f, 0xb0,
+ 0x7b, 0x4a, 0x05, 0xdb, 0x12, 0xa3, 0xad, 0x5c, 0x7e, 0xd4,
+ 0x58, 0x1a, 0xa4, 0xbf, 0x8b, 0x6f, 0x40, 0x1e },
+ { 0x79, 0xc2, 0x80, 0xee, 0x9c, 0xd2, 0xdb, 0x98, 0xbf, 0x24,
+ 0x73, 0x5c, 0xd2, 0xf1, 0x46, 0xfe, 0x4d, 0x7b, 0xb3, 0x61,
+ 0x82, 0xe8, 0xc5, 0xba, 0x92, 0x32, 0xb3, 0x7e, 0xa6, 0x00,
+ 0x85, 0x15, 0x31, 0xfc, 0x58, 0x82, 0xf8, 0xf2, 0xc0, 0x75,
+ 0x8c, 0xcd, 0x79, 0xb0, 0x67, 0x62, 0x2c, 0x9e, 0xe0, 0xcf,
+ 0x16, 0xee, 0xc4, 0x7c, 0xa8, 0x96, 0xd7, 0xf6, 0x58, 0x52,
+ 0x7c, 0x25, 0x0c, 0x78, 0x57, 0x3e, 0xbd, 0x17, 0x51, 0xfd,
+ 0xff, 0x34, 0x56, 0x2a, 0xbc, 0xfa, 0x67, 0x7d, 0x0a, 0x92,
+ 0xba, 0xda, 0xd7, 0xb1, 0x02, 0xf7, 0x1b, 0xef, 0x3e, 0x2c,
+ 0xfb, 0xd9, 0xb3, 0x85, 0x38, 0x2a, 0x24, 0x2f, 0xa7, 0xf9,
+ 0x62, 0x74, 0x46, 0x17, 0x5f, 0x02, 0x73, 0x7d, 0x48, 0x76,
+ 0xee, 0xdf, 0x6e, 0x13, 0x88, 0xc2, 0x10, 0x78, 0xa7, 0xad,
+ 0x62, 0x66, 0xb2, 0x5e, 0x9c, 0x5a, 0x8e, 0xdf },
+ { 0x75, 0x80, 0x73, 0xa4, 0xa9, 0xe3, 0xff, 0x4f, 0x9f, 0xd9,
+ 0xf7, 0x91, 0x52, 0xc8, 0xf4, 0x08, 0x3f, 0x9d, 0xd5, 0x78,
+ 0xb5, 0xbe, 0x5b, 0xe4, 0x26, 0xdb, 0xc5, 0x8e, 0x73, 0xe4,
+ 0x0e, 0x3b, 0xe0, 0xb0, 0x44, 0x26, 0xb5, 0x1e, 0x38, 0xbc,
+ 0x3e, 0x3a, 0xf3, 0xc6, 0x9c, 0x66, 0x27, 0x4b, 0x1b, 0x2b,
+ 0xf8, 0x9f, 0x18, 0x3e, 0xae, 0x42, 0x6c, 0x51, 0x23, 0x5c,
+ 0xce, 0xe6, 0xb6, 0x06, 0x57, 0x0c, 0x5b, 0xb7, 0x81, 0x6b,
+ 0x62, 0x30, 0x24, 0xd2, 0x8c, 0xa0, 0x6b, 0xc1, 0x4b, 0x2e,
+ 0x17, 0xaa, 0x5a, 0xea, 0x8e, 0x1a, 0xb8, 0x20, 0x73, 0x39,
+ 0xe7, 0x21, 0x67, 0x6d, 0xe2, 0x50, 0xab, 0x83, 0x89, 0x97,
+ 0x82, 0xc1, 0x00, 0x1c, 0xac, 0xf0, 0x64, 0xdc, 0x9f, 0xc4,
+ 0x88, 0x5e, 0xa8, 0xc0, 0x49, 0x16, 0xb0, 0x4a, 0xc4, 0x8e,
+ 0xbd, 0xcc, 0x82, 0x03, 0xf2, 0xb4, 0x81, 0x22 },
+ { 0x3f, 0x3e, 0x34, 0x58, 0xfa, 0xf6, 0x6a, 0xa8, 0x93, 0x42,
+ 0xa7, 0xfa, 0x86, 0x61, 0xd3, 0x2d, 0xfb, 0xab, 0x9f, 0xa1,
+ 0x49, 0xe9, 0xe1, 0x04, 0x06, 0xe5, 0x25, 0x99, 0xb4, 0xfd,
+ 0x4c, 0x45, 0x2d, 0x21, 0x64, 0x76, 0x08, 0xc7, 0xf3, 0xff,
+ 0x3d, 0x0b, 0x10, 0xbf, 0xfd, 0x7b, 0xe6, 0xc7, 0xbd, 0xa4,
+ 0xc8, 0x24, 0x29, 0x7e, 0xe2, 0x03, 0x4b, 0xc0, 0xd0, 0x30,
+ 0xa9, 0xfd, 0x97, 0x83, 0x14, 0x64, 0x6e, 0x53, 0xcf, 0x4b,
+ 0x84, 0x32, 0xde, 0xf4, 0x44, 0xc1, 0x13, 0x66, 0x84, 0x3a,
+ 0x56, 0xd5, 0x75, 0x0c, 0x3c, 0x47, 0x4d, 0xbd, 0x2e, 0x16,
+ 0x6d, 0xe7, 0xc8, 0xa0, 0xe2, 0x4c, 0xc5, 0xd1, 0x8a, 0x2a,
+ 0x75, 0x53, 0x66, 0x07, 0xe8, 0x4b, 0xd3, 0x85, 0xac, 0x79,
+ 0x54, 0x13, 0xf2, 0x06, 0xbf, 0xd6, 0x13, 0xa2, 0xa1, 0xb6,
+ 0x7d, 0x27, 0xb0, 0x57, 0x86, 0x91, 0xca, 0x22 },
+ { 0x64, 0x0d, 0x20, 0xc4, 0x34, 0xc2, 0x94, 0xef, 0x1e, 0x9e,
+ 0x17, 0xed, 0x6c, 0x48, 0x29, 0x5e, 0x44, 0x1e, 0xed, 0xe2,
+ 0x2a, 0x0e, 0x2f, 0x63, 0x56, 0xd9, 0xf8, 0x07, 0x3c, 0x83,
+ 0x14, 0xae, 0xe7, 0x7b, 0x2e, 0x4c, 0xc1, 0x43, 0x3d, 0x67,
+ 0xc8, 0xee, 0x32, 0x3e, 0x30, 0xc7, 0x8d, 0x2b, 0xd8, 0x2d,
+ 0x5e, 0x9f, 0x65, 0x45, 0x7d, 0x95, 0x87, 0x34, 0xed, 0xdc,
+ 0xfc, 0x40, 0xe8, 0x1b, 0xb7, 0x63, 0x87, 0x58, 0x35, 0x29,
+ 0x2c, 0x32, 0xb8, 0xfa, 0x29, 0x56, 0x19, 0x9e, 0x5f, 0x98,
+ 0xf9, 0x9e, 0xe9, 0xdf, 0xed, 0xe1, 0xf0, 0x9c, 0x8a, 0x69,
+ 0x65, 0x53, 0xfd, 0x9b, 0xb9, 0xc3, 0x42, 0x3e, 0xca, 0x49,
+ 0x51, 0x5a, 0x29, 0x35, 0x02, 0x76, 0xcd, 0x9c, 0x9b, 0xf4,
+ 0xef, 0xf5, 0xb6, 0x77, 0xd4, 0xac, 0x49, 0xdf, 0x64, 0xeb,
+ 0x51, 0xec, 0x35, 0xaf, 0x95, 0x15, 0x97, 0xaa },
+ { 0x0f, 0x9c, 0x1c, 0xa8, 0xc0, 0xd9, 0x28, 0x16, 0xb9, 0x68,
+ 0x90, 0x2a, 0xc7, 0x2e, 0x05, 0xc1, 0x8e, 0xe4, 0x0d, 0x66,
+ 0x34, 0x9a, 0xa6, 0x39, 0xf3, 0x9e, 0x46, 0x09, 0x91, 0x2b,
+ 0xd1, 0x7a, 0xdf, 0xe5, 0x2b, 0x11, 0x87, 0x6c, 0x29, 0xc3,
+ 0x69, 0xa0, 0x74, 0xb6, 0x28, 0x57, 0x42, 0xe8, 0xb6, 0x30,
+ 0x2b, 0x33, 0x0f, 0x32, 0xd3, 0x67, 0x8b, 0xc4, 0x09, 0x4d,
+ 0x57, 0x46, 0x0e, 0x65, 0xca, 0x8e, 0x35, 0x1d, 0xfc, 0x9f,
+ 0x1b, 0x73, 0x4e, 0x46, 0x1a, 0xca, 0x6d, 0x4a, 0xd4, 0xc2,
+ 0x29, 0xb6, 0xef, 0x13, 0x30, 0x3f, 0x07, 0xa8, 0x8d, 0x9d,
+ 0x47, 0xdc, 0x25, 0x49, 0xfc, 0x46, 0xd8, 0x0b, 0xdc, 0xfc,
+ 0x1d, 0xe5, 0x0d, 0xb7, 0xb3, 0x6e, 0x74, 0x07, 0x45, 0xac,
+ 0xd5, 0x2a, 0x07, 0x4c, 0x35, 0x45, 0xf3, 0x15, 0x05, 0x3a,
+ 0x4e, 0x9a, 0x0b, 0x8e, 0x32, 0x84, 0xd5, 0x13 },
+ { 0x7e, 0x31, 0xc1, 0x2f, 0x45, 0xd3, 0x6e, 0xc5, 0x34, 0xbd,
+ 0x9b, 0xa7, 0x09, 0x8a, 0x82, 0x40, 0x9b, 0x9a, 0xce, 0xc6,
+ 0xe6, 0xe6, 0xff, 0x33, 0x63, 0x94, 0x9c, 0x91, 0x3e, 0x72,
+ 0x63, 0xf8, 0x3d, 0xb4, 0x7f, 0x70, 0xc6, 0x5e, 0x3e, 0xaf,
+ 0x48, 0x59, 0x3d, 0xb8, 0xb6, 0x63, 0x0f, 0xb1, 0x83, 0x20,
+ 0x27, 0x89, 0xd7, 0x69, 0x4f, 0x9b, 0x58, 0xad, 0x74, 0xb0,
+ 0x7b, 0x29, 0x0d, 0xfd, 0x5e, 0xa6, 0x0d, 0xfa, 0x66, 0x08,
+ 0xb3, 0x88, 0xcf, 0x25, 0x67, 0x30, 0x0a, 0x3b, 0x13, 0x26,
+ 0x73, 0x13, 0x99, 0xa3, 0x0b, 0x4d, 0xca, 0x09, 0x4b, 0x63,
+ 0x88, 0x54, 0xd5, 0x37, 0x34, 0x51, 0x72, 0xc9, 0x18, 0xcb,
+ 0x65, 0xe4, 0x08, 0xf9, 0x13, 0xa3, 0x20, 0xd8, 0x97, 0xf0,
+ 0xc5, 0xcc, 0xb6, 0xaa, 0x53, 0x47, 0x15, 0xd3, 0x62, 0x8c,
+ 0x1e, 0xbb, 0xaa, 0xb3, 0x67, 0x43, 0x3d, 0xf3 },
+ { 0x1a, 0x21, 0x9c, 0x45, 0x32, 0x6d, 0x53, 0x57, 0x4d, 0xe4,
+ 0x1a, 0x30, 0x7e, 0x23, 0xba, 0x60, 0xac, 0x19, 0x6c, 0xf5,
+ 0x33, 0x7c, 0xa1, 0xbb, 0xc5, 0x3b, 0x7e, 0x03, 0xfc, 0x4f,
+ 0xbb, 0x2e, 0x86, 0xbe, 0x92, 0xd3, 0xef, 0xc4, 0xd9, 0x3c,
+ 0x4f, 0x64, 0xee, 0x41, 0x0e, 0x2b, 0x37, 0x47, 0x74, 0x1f,
+ 0x0d, 0x73, 0x15, 0x6c, 0x4e, 0xe1, 0xfa, 0x91, 0x92, 0x5d,
+ 0xdc, 0xc7, 0x22, 0x23, 0x76, 0xb3, 0xbf, 0xad, 0xfc, 0x94,
+ 0x70, 0x76, 0x33, 0x6e, 0x30, 0x9e, 0xde, 0x13, 0xfd, 0x1b,
+ 0x7a, 0x46, 0x31, 0xbe, 0x79, 0x69, 0xa1, 0x0d, 0xfd, 0xd5,
+ 0xfc, 0x30, 0xcf, 0xfb, 0xb4, 0x06, 0x66, 0x0c, 0x8d, 0xfa,
+ 0x95, 0x9c, 0xb3, 0xbc, 0xb9, 0xc3, 0x00, 0x5f, 0x94, 0x43,
+ 0x1f, 0x97, 0x1e, 0xfa, 0xcb, 0x00, 0x24, 0xab, 0x61, 0xd8,
+ 0xbe, 0x28, 0x1d, 0x68, 0x0d, 0xfd, 0x2d, 0xd7 },
+ { 0x17, 0xaa, 0xa9, 0x99, 0xbc, 0x90, 0x19, 0x2f, 0xe0, 0x2b,
+ 0xcf, 0x77, 0xb6, 0xd0, 0xbf, 0x93, 0x6a, 0xc1, 0x53, 0x7e,
+ 0xf8, 0x03, 0x06, 0x62, 0xf0, 0x4c, 0xe5, 0x90, 0xbe, 0xa6,
+ 0x94, 0x03, 0x73, 0xcd, 0x50, 0x2d, 0x43, 0x74, 0x42, 0xd1,
+ 0x92, 0xff, 0x23, 0x29, 0x95, 0x56, 0x6b, 0xe6, 0x42, 0x2a,
+ 0x33, 0x0a, 0xc4, 0xf8, 0x9c, 0xb8, 0x95, 0x3e, 0x69, 0xb2,
+ 0x5b, 0x53, 0xf1, 0xc3, 0x4d, 0x6c, 0x45, 0x7f, 0x69, 0xe5,
+ 0x7f, 0x8e, 0xfd, 0x0d, 0xe2, 0xcb, 0x2b, 0x0c, 0x81, 0x20,
+ 0x78, 0xe1, 0x0e, 0xc1, 0x82, 0xcc, 0x60, 0x43, 0x99, 0x7c,
+ 0x8e, 0x35, 0xa2, 0xfc, 0x0e, 0xdb, 0xc0, 0xce, 0xc2, 0xe2,
+ 0xff, 0xdc, 0x77, 0x71, 0xc2, 0x63, 0x90, 0x67, 0x3d, 0x8a,
+ 0x19, 0x2f, 0x2e, 0x23, 0x18, 0x06, 0x7b, 0x6c, 0x99, 0x63,
+ 0xfd, 0xcf, 0x7e, 0xf8, 0xaa, 0x4d, 0xb0, 0xbc },
+ { 0x6b, 0x28, 0x2a, 0xf0, 0xa5, 0xf3, 0xb2, 0x4a, 0xfb, 0xd5,
+ 0xff, 0x8c, 0x22, 0x64, 0x74, 0xbc, 0x3b, 0x4b, 0x2d, 0x8f,
+ 0xbe, 0x76, 0x08, 0xef, 0xa2, 0x8f, 0xd8, 0x6b, 0xa5, 0xbf,
+ 0xd2, 0x67, 0x0f, 0x45, 0x6a, 0x4c, 0x0f, 0x97, 0xfa, 0x97,
+ 0x78, 0xbe, 0xdd, 0xe1, 0x21, 0x4f, 0x96, 0xc5, 0xe8, 0x92,
+ 0x5e, 0x91, 0xb4, 0x3b, 0x68, 0x13, 0x0a, 0x44, 0xa0, 0xe5,
+ 0x0e, 0x4a, 0x49, 0xbe, 0x94, 0xb5, 0x5c, 0x87, 0x4f, 0xf0,
+ 0x6b, 0x25, 0xf4, 0x00, 0xac, 0x1e, 0xdd, 0x20, 0x45, 0xc0,
+ 0x72, 0x17, 0xfd, 0xd9, 0xbd, 0xd6, 0x72, 0xcf, 0x23, 0xf9,
+ 0x9c, 0x36, 0xdd, 0x95, 0xf7, 0xa9, 0xa6, 0xff, 0x3b, 0x35,
+ 0xea, 0x17, 0xe2, 0x7c, 0x1a, 0x14, 0x40, 0xe5, 0x5b, 0x88,
+ 0x46, 0x2f, 0x83, 0x5d, 0xee, 0x43, 0x3b, 0x94, 0x68, 0x51,
+ 0x0d, 0x3d, 0x56, 0x43, 0x8e, 0x55, 0xdb, 0x2e },
+ { 0x6d, 0x4f, 0x5d, 0x23, 0x54, 0x70, 0x6e, 0xbf, 0xb6, 0x64,
+ 0xf5, 0x29, 0xee, 0x8d, 0x97, 0x62, 0x13, 0xe6, 0x44, 0x27,
+ 0x2b, 0x41, 0x2d, 0xfb, 0x42, 0x9d, 0x16, 0x7b, 0x48, 0x02,
+ 0xc2, 0x45, 0x76, 0xa5, 0x45, 0xc6, 0xc2, 0xbe, 0x9f, 0x3d,
+ 0x80, 0xb0, 0xbd, 0x68, 0xb2, 0x30, 0x6b, 0x0e, 0xee, 0x37,
+ 0x8b, 0xf4, 0xa8, 0x02, 0x45, 0xde, 0x69, 0xe9, 0xbe, 0x5c,
+ 0x59, 0x45, 0x50, 0x88, 0x2a, 0x2b, 0x2d, 0x2d, 0x0b, 0xfd,
+ 0x87, 0xb1, 0x10, 0x2d, 0xdf, 0x09, 0x8f, 0xd2, 0xfb, 0x64,
+ 0x14, 0x5d, 0x94, 0x66, 0x95, 0xa7, 0xac, 0xb4, 0x91, 0x14,
+ 0x14, 0xd3, 0x08, 0x3e, 0x16, 0xc4, 0x3f, 0x94, 0x66, 0xd3,
+ 0x75, 0x54, 0x78, 0x33, 0x72, 0xbd, 0x6e, 0x3d, 0xeb, 0x44,
+ 0x68, 0x42, 0x59, 0x1c, 0x38, 0xd6, 0xa4, 0x45, 0xe2, 0x8c,
+ 0x78, 0xfc, 0x02, 0x5f, 0x63, 0x41, 0xa5, 0x95 },
+ { 0x4a, 0xaf, 0x0b, 0x4f, 0xd6, 0x5d, 0x34, 0xad, 0x6e, 0xda,
+ 0x93, 0xc4, 0x40, 0xdb, 0x81, 0xb4, 0x55, 0x1f, 0xc8, 0x72,
+ 0xb9, 0x97, 0x7d, 0x90, 0xe7, 0x8b, 0xd7, 0xa5, 0x74, 0x07,
+ 0x0b, 0xb3, 0x9c, 0x2a, 0x5e, 0x92, 0x58, 0xf3, 0x75, 0x80,
+ 0xb2, 0x08, 0x51, 0x70, 0x01, 0x16, 0xde, 0xb6, 0xe0, 0xfe,
+ 0x46, 0x78, 0x24, 0xd0, 0x5f, 0x74, 0xd2, 0xf0, 0xa7, 0xdd,
+ 0x2f, 0x07, 0xae, 0xa3, 0xa9, 0xe3, 0xd5, 0x9f, 0x79, 0xb7,
+ 0x8a, 0x26, 0x72, 0xeb, 0xa5, 0x7e, 0x88, 0x18, 0x43, 0x4d,
+ 0x02, 0x8d, 0xca, 0x62, 0x63, 0xc9, 0x64, 0x87, 0x3e, 0x30,
+ 0x8e, 0x6f, 0xf3, 0x7d, 0xcb, 0xa6, 0x33, 0x5c, 0xe6, 0xce,
+ 0xa7, 0xac, 0x78, 0x1e, 0x0a, 0x12, 0x6d, 0x42, 0xb3, 0xb8,
+ 0x1e, 0x5b, 0xfd, 0xc8, 0x07, 0xe0, 0x7b, 0xb6, 0xd0, 0xbf,
+ 0x35, 0xc8, 0xf2, 0xb6, 0x00, 0xba, 0x9f, 0x88 },
+ { 0x8b, 0x2c, 0xbd, 0x39, 0x82, 0xbc, 0x63, 0x37, 0xa1, 0xd4,
+ 0x16, 0x5b, 0x1c, 0x2e, 0x14, 0xd7, 0xf9, 0x9c, 0x52, 0x6b,
+ 0xd6, 0xeb, 0xf3, 0xa9, 0x14, 0x4d, 0xad, 0xe1, 0xa7, 0x21,
+ 0xec, 0xd9, 0x72, 0xae, 0xc5, 0x77, 0xb2, 0xc1, 0x1f, 0xb1,
+ 0x16, 0xde, 0xde, 0x4e, 0x09, 0x70, 0x18, 0xc7, 0x11, 0xa5,
+ 0xa8, 0x04, 0x8b, 0xe4, 0x4a, 0xa0, 0x06, 0xf9, 0x83, 0x6b,
+ 0x85, 0x72, 0x86, 0x36, 0x64, 0xde, 0x98, 0x9a, 0x25, 0xbc,
+ 0x04, 0xdb, 0xc1, 0xcd, 0xd5, 0x2f, 0xa0, 0x61, 0xdb, 0xdb,
+ 0x4e, 0xef, 0x38, 0x6b, 0x8b, 0xd9, 0xc4, 0x66, 0xb2, 0x49,
+ 0x0f, 0xc0, 0x92, 0x1d, 0x32, 0xdd, 0xd8, 0xdb, 0xfa, 0xb5,
+ 0x17, 0x3b, 0x86, 0x85, 0xef, 0x3c, 0xae, 0x87, 0x8f, 0xa3,
+ 0xec, 0x58, 0xb0, 0x9e, 0x7d, 0xad, 0xbc, 0x18, 0x1e, 0xad,
+ 0x9b, 0xef, 0x25, 0x06, 0x35, 0x14, 0xc7, 0xaf },
+ { 0x57, 0xe2, 0x83, 0x04, 0x7d, 0xbe, 0x36, 0x70, 0x22, 0x0e,
+ 0xea, 0xec, 0x8f, 0xc5, 0xc8, 0x31, 0x86, 0xc2, 0x82, 0x4e,
+ 0x87, 0x4c, 0xcd, 0x58, 0x39, 0x9a, 0x79, 0xc8, 0xf0, 0x24,
+ 0x3c, 0xf5, 0x23, 0xdf, 0x80, 0xe6, 0x08, 0x6e, 0x33, 0xf6,
+ 0x04, 0x1e, 0xc0, 0xb5, 0x45, 0x61, 0x6b, 0xfd, 0xd1, 0x55,
+ 0xf5, 0x78, 0x03, 0xbf, 0x1d, 0x4c, 0xcc, 0x64, 0xee, 0xb3,
+ 0x35, 0xde, 0xea, 0xe7, 0x9a, 0xa3, 0xf4, 0xb3, 0xee, 0x40,
+ 0x5e, 0x89, 0xc7, 0x0c, 0xa9, 0x3b, 0x06, 0xba, 0x06, 0xd2,
+ 0xca, 0x14, 0xf1, 0xa7, 0xa3, 0x19, 0x48, 0x8a, 0xbd, 0x32,
+ 0x98, 0xd1, 0x48, 0x7c, 0x2a, 0x2d, 0x3f, 0xc2, 0x57, 0xb3,
+ 0xc5, 0x76, 0x2b, 0x9c, 0x83, 0x07, 0xd1, 0x30, 0xc6, 0x34,
+ 0xea, 0x45, 0x0b, 0xa2, 0x02, 0xf6, 0xcf, 0x9d, 0x42, 0xec,
+ 0x28, 0xec, 0x1b, 0xf2, 0x8a, 0x52, 0xe9, 0x91 },
+ { 0x4f, 0x12, 0xe0, 0x37, 0x69, 0x6f, 0xfd, 0xa6, 0xe8, 0xbe,
+ 0xe9, 0xd4, 0xc9, 0x1d, 0x60, 0x63, 0xd0, 0xd3, 0xcb, 0x56,
+ 0x19, 0xd4, 0xa2, 0xd7, 0x3a, 0xc0, 0xfb, 0xd5, 0x7c, 0xba,
+ 0x21, 0x7d, 0xeb, 0x28, 0x9d, 0x0a, 0xa9, 0x36, 0x17, 0xb0,
+ 0x5e, 0xcb, 0xbc, 0x8c, 0xad, 0x54, 0xef, 0x05, 0xef, 0x96,
+ 0xf7, 0x31, 0x53, 0xde, 0x1b, 0x2f, 0x96, 0xb3, 0x7e, 0x87,
+ 0xb6, 0x05, 0x47, 0x05, 0x46, 0x98, 0x99, 0x25, 0x20, 0x30,
+ 0xfa, 0x5a, 0x76, 0xd4, 0xf2, 0xb7, 0x0c, 0xa3, 0x76, 0x01,
+ 0x65, 0xc0, 0xf4, 0x92, 0x53, 0x39, 0x8a, 0x72, 0x65, 0x5c,
+ 0x4b, 0x9b, 0x28, 0x42, 0x3b, 0x20, 0xd7, 0x6b, 0xf7, 0x5e,
+ 0x52, 0x2b, 0xc8, 0x8d, 0x40, 0x44, 0xad, 0xba, 0x80, 0x49,
+ 0x84, 0x36, 0xbd, 0xd0, 0x6a, 0x99, 0x8b, 0xeb, 0xb1, 0xd2,
+ 0x6e, 0x60, 0xb6, 0x98, 0xfb, 0xcd, 0xf6, 0x66 },
+ { 0x83, 0xd2, 0x33, 0x3e, 0xb1, 0x26, 0x6f, 0x91, 0xa8, 0xf7,
+ 0x8e, 0xa7, 0x58, 0x58, 0xaf, 0xb2, 0x1a, 0x49, 0x6e, 0xa9,
+ 0x5b, 0x52, 0x1e, 0xcb, 0x73, 0xe6, 0x9c, 0x6e, 0xa9, 0x44,
+ 0x8b, 0x02, 0xf8, 0x88, 0xe9, 0x2c, 0xf2, 0x77, 0xba, 0xb1,
+ 0x45, 0xb2, 0x32, 0xb2, 0x9b, 0xd6, 0x44, 0x4a, 0x61, 0xa0,
+ 0x86, 0x6d, 0x32, 0x02, 0x53, 0x71, 0x9d, 0x9e, 0xd8, 0x9f,
+ 0xf9, 0xc1, 0xd4, 0xdd, 0x8c, 0x34, 0xd2, 0x2c, 0xb9, 0x5a,
+ 0xe1, 0x6a, 0x74, 0xe7, 0xce, 0xe7, 0x93, 0xc4, 0x80, 0x4e,
+ 0xfb, 0x6b, 0xa8, 0x8c, 0x70, 0xa8, 0xa0, 0xfa, 0x36, 0x46,
+ 0x4c, 0x65, 0x14, 0x6d, 0x13, 0x20, 0xfa, 0x15, 0xb4, 0x84,
+ 0x4b, 0x28, 0x4e, 0x2a, 0x12, 0x46, 0xa4, 0x54, 0x73, 0x83,
+ 0x81, 0x34, 0x80, 0x4a, 0x5c, 0x55, 0x37, 0x86, 0x51, 0x9a,
+ 0x4c, 0xcf, 0xa4, 0x22, 0x15, 0xf1, 0xa6, 0x10 },
+ { 0x73, 0x62, 0xf1, 0x3e, 0xc5, 0xa3, 0x16, 0x21, 0x46, 0x35,
+ 0x32, 0x15, 0x2f, 0x40, 0xa5, 0x5b, 0x82, 0x26, 0xb6, 0xaf,
+ 0xb7, 0xd1, 0xe5, 0x86, 0x8e, 0xdb, 0x61, 0x22, 0xf8, 0xe8,
+ 0x6e, 0xf3, 0x28, 0xb2, 0x28, 0x0e, 0x3d, 0x40, 0x75, 0x4c,
+ 0xa0, 0x1e, 0x0f, 0x59, 0x6b, 0xf7, 0x6d, 0xad, 0x17, 0xde,
+ 0x4b, 0xfe, 0xd5, 0xbe, 0xe3, 0x97, 0xd6, 0xb4, 0x3e, 0xf6,
+ 0xf4, 0x5d, 0x9f, 0xbb, 0xb3, 0x97, 0x8d, 0xb8, 0xd8, 0x54,
+ 0xdf, 0xb2, 0x52, 0x8f, 0xef, 0x00, 0x93, 0xf5, 0x5f, 0x0a,
+ 0xe8, 0x12, 0x01, 0x19, 0x70, 0xe7, 0x3d, 0x77, 0x15, 0x9d,
+ 0x66, 0x60, 0xa8, 0x11, 0x7a, 0x87, 0x69, 0xf1, 0xf2, 0x88,
+ 0x89, 0x3c, 0xd6, 0x96, 0x05, 0xb6, 0xab, 0x30, 0x18, 0xd2,
+ 0x24, 0x1b, 0xa1, 0xee, 0x1a, 0xe1, 0x50, 0xa2, 0xfc, 0x9c,
+ 0x1c, 0x63, 0x32, 0x88, 0x67, 0xb4, 0x78, 0xd7 },
+ { 0x2f, 0x10, 0x69, 0x3f, 0xa3, 0x8c, 0x0e, 0xad, 0xd9, 0xb1,
+ 0x6f, 0x02, 0xda, 0x0a, 0x20, 0xa8, 0xf0, 0x86, 0x1d, 0x92,
+ 0x90, 0x98, 0x36, 0x95, 0x1f, 0xc3, 0x9b, 0xac, 0x89, 0xf0,
+ 0xbf, 0x0b, 0xe7, 0xaf, 0x9c, 0xd7, 0x2f, 0x2b, 0x39, 0x9e,
+ 0x0e, 0xb1, 0xe7, 0x15, 0xff, 0x56, 0x8f, 0x64, 0x2c, 0x91,
+ 0x15, 0x4e, 0xae, 0xc8, 0x91, 0xf9, 0x63, 0xe2, 0xfd, 0xbf,
+ 0xb6, 0xc1, 0xa4, 0x55, 0xb6, 0x51, 0x0c, 0xd8, 0xe3, 0xa8,
+ 0xd0, 0xd5, 0xd9, 0x36, 0x1d, 0x68, 0x39, 0x87, 0x79, 0x5e,
+ 0x37, 0x6f, 0x4f, 0x58, 0xf0, 0xaa, 0x86, 0x08, 0xbb, 0xf0,
+ 0xa8, 0x1a, 0x4b, 0x6f, 0xbb, 0xf4, 0x18, 0x94, 0x56, 0x88,
+ 0x81, 0x4b, 0x49, 0x47, 0x50, 0xa5, 0xce, 0xce, 0xd2, 0x19,
+ 0x4f, 0x1b, 0x8c, 0xc0, 0xa6, 0x5f, 0xa5, 0x1c, 0x36, 0x57,
+ 0x79, 0x2e, 0xb2, 0x7c, 0x73, 0xc0, 0xc4, 0x30 },
+ { 0x98, 0x5f, 0x83, 0xe4, 0x4f, 0xe7, 0xa0, 0x43, 0x27, 0x75,
+ 0xdb, 0xdd, 0x96, 0x43, 0x7c, 0xdb, 0x1e, 0xff, 0x68, 0xd4,
+ 0xad, 0x6f, 0x19, 0x40, 0x5b, 0x53, 0xd2, 0x79, 0x9d, 0xaa,
+ 0x9e, 0x4f, 0x25, 0x51, 0xc8, 0xe4, 0xaf, 0x39, 0x53, 0xc8,
+ 0x7c, 0x7a, 0xfb, 0x14, 0x08, 0xea, 0x2f, 0x6e, 0x82, 0x8c,
+ 0x3a, 0x05, 0xd5, 0x9c, 0xda, 0x99, 0xa6, 0x86, 0xae, 0x49,
+ 0x47, 0xf3, 0x82, 0x83, 0x64, 0xba, 0x66, 0xfc, 0x8f, 0xaa,
+ 0x62, 0x9e, 0x67, 0x59, 0xac, 0xfe, 0x10, 0xd6, 0x33, 0xac,
+ 0x9c, 0xbd, 0x11, 0x13, 0xdc, 0x96, 0xa2, 0x01, 0x1f, 0xb2,
+ 0xf8, 0x9f, 0x36, 0x9e, 0xe5, 0x48, 0x04, 0xb6, 0x18, 0x91,
+ 0x1e, 0xd6, 0x06, 0x26, 0xe4, 0x68, 0xbf, 0xd6, 0xa9, 0xf6,
+ 0x35, 0xa6, 0xf9, 0x74, 0x84, 0x2f, 0x2f, 0xd9, 0x08, 0x7b,
+ 0x07, 0xa6, 0xce, 0x91, 0x0c, 0x06, 0xde, 0xd2 },
+ { 0x0c, 0x88, 0xe5, 0x40, 0x0f, 0xe9, 0x62, 0xf1, 0x54, 0xd7,
+ 0x79, 0xd5, 0x50, 0xdc, 0xc7, 0x99, 0xbb, 0xf1, 0x5a, 0x6f,
+ 0x1e, 0x78, 0x1c, 0xa7, 0x2d, 0x9f, 0x17, 0x9c, 0x0d, 0x8c,
+ 0xbc, 0x2e, 0x68, 0xfd, 0xda, 0xa9, 0x92, 0xc0, 0x03, 0xb3,
+ 0x07, 0x01, 0x9c, 0x93, 0x1a, 0x44, 0x3c, 0xfa, 0xb0, 0x7d,
+ 0x2c, 0xd1, 0xe9, 0xdf, 0x45, 0xcc, 0xa5, 0x25, 0x9e, 0x63,
+ 0x9a, 0xbc, 0x45, 0x2a, 0xee, 0x66, 0x84, 0xba, 0xe3, 0x4c,
+ 0x5c, 0x22, 0x5a, 0xc5, 0xee, 0xa3, 0xf8, 0xb2, 0x4f, 0x0e,
+ 0x3d, 0xc3, 0xf0, 0x76, 0x9c, 0x8a, 0xc1, 0xe1, 0x0c, 0x5b,
+ 0x02, 0x8b, 0x74, 0xf4, 0x1b, 0x68, 0x70, 0x79, 0xcf, 0x02,
+ 0xed, 0x94, 0x33, 0x40, 0x4c, 0x11, 0x20, 0x18, 0x39, 0xd6,
+ 0xb5, 0x2d, 0x70, 0x13, 0x11, 0x60, 0xc2, 0x4b, 0x57, 0x51,
+ 0x89, 0x60, 0x3c, 0x16, 0xea, 0xf4, 0x52, 0x94 },
+ { 0x8e, 0x25, 0x60, 0xb8, 0xaf, 0x11, 0x07, 0x15, 0x4e, 0x5d,
+ 0xe4, 0x99, 0x3a, 0x25, 0xce, 0xd6, 0xeb, 0xae, 0xa0, 0x19,
+ 0xfa, 0x87, 0x77, 0x2f, 0x89, 0xf3, 0x36, 0x27, 0x3b, 0x3a,
+ 0x2c, 0xd7, 0x8c, 0x17, 0xae, 0x85, 0x98, 0x7b, 0x90, 0x7a,
+ 0x8c, 0x19, 0xfd, 0x8f, 0x92, 0x2d, 0xbc, 0xe8, 0x67, 0x4e,
+ 0xac, 0x95, 0x5a, 0x33, 0x06, 0x5a, 0xeb, 0xbb, 0x1f, 0xaf,
+ 0xee, 0xd0, 0xe1, 0x97, 0x7b, 0x32, 0x8e, 0x6f, 0xf2, 0xbc,
+ 0x37, 0x92, 0x75, 0x98, 0x84, 0x64, 0xb8, 0x0e, 0x32, 0xae,
+ 0xbb, 0x9d, 0x5a, 0x38, 0xf7, 0x4f, 0x8d, 0x3a, 0xe2, 0x80,
+ 0x14, 0xc1, 0x07, 0x5e, 0x3c, 0x8e, 0xce, 0xca, 0xf0, 0x84,
+ 0x8a, 0x75, 0x3e, 0xf2, 0x33, 0x4c, 0x9d, 0x9e, 0x5a, 0xeb,
+ 0xc6, 0x80, 0xf7, 0x5b, 0x4b, 0xf6, 0x3a, 0x3c, 0xab, 0x6a,
+ 0x84, 0xf7, 0x1a, 0x6a, 0xe8, 0xf4, 0x43, 0x57 },
+ { 0x59, 0x00, 0x5f, 0x22, 0x83, 0x24, 0xf2, 0xe5, 0xfe, 0xf3,
+ 0xd9, 0x2b, 0x92, 0xfd, 0x9a, 0x29, 0x88, 0xbe, 0x0c, 0x92,
+ 0x8f, 0x92, 0x23, 0x15, 0x23, 0x0c, 0xc7, 0x7c, 0x53, 0x91,
+ 0xca, 0x50, 0xb4, 0x1a, 0xb2, 0x65, 0x23, 0x31, 0xd6, 0x11,
+ 0x61, 0x27, 0x5a, 0xc2, 0x0a, 0xdf, 0x09, 0xc7, 0x40, 0x40,
+ 0x34, 0x5c, 0x8e, 0x0a, 0x28, 0xab, 0x89, 0x29, 0xd4, 0xde,
+ 0x97, 0x52, 0x3b, 0x1f, 0x60, 0x78, 0x34, 0x0a, 0x65, 0x10,
+ 0x46, 0xd5, 0x27, 0x19, 0xdb, 0x5d, 0xa3, 0x83, 0xbb, 0xa7,
+ 0x49, 0xa8, 0x02, 0x00, 0xb1, 0x16, 0x01, 0x18, 0x1e, 0x0b,
+ 0x15, 0xcd, 0x3a, 0x94, 0x08, 0xff, 0x22, 0x23, 0x76, 0x32,
+ 0x9d, 0xfd, 0x95, 0x0e, 0xb6, 0x38, 0x28, 0x31, 0x9c, 0xdd,
+ 0x27, 0xc7, 0x45, 0xa1, 0x07, 0x9f, 0xba, 0xb2, 0xcf, 0x9e,
+ 0x56, 0xd3, 0x74, 0x6c, 0x31, 0x41, 0xab, 0xa6 },
+ { 0x57, 0xa7, 0x8e, 0x26, 0xd7, 0x83, 0xdf, 0x6e, 0xe4, 0x49,
+ 0x59, 0x36, 0xb4, 0x3b, 0xae, 0x8d, 0xe9, 0x79, 0x18, 0x51,
+ 0x32, 0x62, 0xa3, 0x38, 0x00, 0x85, 0xac, 0x6e, 0x17, 0x38,
+ 0x2d, 0xa1, 0x00, 0x80, 0xfc, 0x0c, 0xf3, 0x9e, 0xad, 0x9c,
+ 0x2d, 0xf1, 0x90, 0xac, 0xb0, 0xe0, 0x86, 0x18, 0x97, 0x71,
+ 0x43, 0x01, 0x44, 0xa6, 0x63, 0xda, 0x19, 0x17, 0x57, 0x14,
+ 0x85, 0x58, 0xca, 0x58, 0xd0, 0xa7, 0x51, 0xf1, 0x48, 0x8c,
+ 0x0d, 0xe6, 0x91, 0x3d, 0xd0, 0x1c, 0xb1, 0x8b, 0x72, 0xb2,
+ 0x54, 0x89, 0x16, 0xf7, 0x3f, 0xf3, 0x89, 0x7f, 0x2b, 0x70,
+ 0x43, 0xb1, 0x50, 0x44, 0x6c, 0xde, 0x8c, 0x97, 0xf9, 0x32,
+ 0x3a, 0x86, 0x56, 0xb6, 0x85, 0xa7, 0x5d, 0x92, 0x66, 0xc5,
+ 0x97, 0x3f, 0xbe, 0x73, 0xaa, 0xc0, 0xe9, 0x66, 0xfb, 0x79,
+ 0x6b, 0xb1, 0x75, 0x0c, 0x3c, 0x4c, 0x1c, 0x74 },
+ { 0x1c, 0xa3, 0x70, 0xc5, 0x81, 0xc4, 0x72, 0xe8, 0x32, 0x51,
+ 0xe4, 0x12, 0x8f, 0x6a, 0xda, 0x87, 0xb4, 0xc5, 0x33, 0xa7,
+ 0xf6, 0xd3, 0x5b, 0x7e, 0x85, 0x24, 0x07, 0xd8, 0x08, 0xd8,
+ 0xa0, 0x36, 0x41, 0x91, 0x04, 0x8f, 0xac, 0x0f, 0x46, 0x2d,
+ 0x6c, 0xa5, 0xef, 0x6a, 0xc4, 0x54, 0xe2, 0x88, 0xe6, 0xec,
+ 0x93, 0x01, 0xe0, 0x84, 0x17, 0xd7, 0x65, 0x8f, 0x58, 0x9b,
+ 0x0c, 0x45, 0x44, 0xd0, 0xec, 0xfa, 0x24, 0x45, 0xad, 0x96,
+ 0xad, 0xc3, 0xc4, 0x6b, 0x39, 0x18, 0x67, 0xf0, 0x86, 0x43,
+ 0xe5, 0xd7, 0xa6, 0x7d, 0xc2, 0x0e, 0xf5, 0x00, 0x9c, 0x8d,
+ 0x59, 0xf5, 0x40, 0xdf, 0x57, 0x9d, 0x72, 0xdf, 0x32, 0x32,
+ 0x33, 0xb9, 0x3d, 0xeb, 0x8c, 0x54, 0x27, 0x83, 0x18, 0x86,
+ 0xcf, 0x3b, 0x2b, 0x49, 0xa9, 0x27, 0x94, 0x10, 0xc3, 0xac,
+ 0x16, 0x1b, 0x34, 0x6f, 0x40, 0xdb, 0xdd, 0xd8 },
+ { 0x25, 0x84, 0xb3, 0x4c, 0x4c, 0x33, 0xac, 0x79, 0x32, 0xdb,
+ 0x52, 0xf4, 0xe6, 0x26, 0x5b, 0xaa, 0x53, 0xd0, 0x44, 0x8a,
+ 0x1d, 0xbd, 0x3b, 0x03, 0x83, 0xbf, 0x46, 0x4e, 0x2e, 0xfd,
+ 0x90, 0x03, 0x71, 0xa1, 0x17, 0x20, 0x2b, 0x42, 0x50, 0x72,
+ 0x6c, 0x31, 0x1c, 0x3d, 0xc0, 0x86, 0x7e, 0x39, 0xca, 0xd4,
+ 0x67, 0xb5, 0x08, 0xcd, 0x1c, 0xd2, 0x0d, 0xd2, 0x80, 0x1d,
+ 0xf9, 0x9d, 0xae, 0x74, 0x22, 0x4b, 0x28, 0x82, 0xe1, 0x88,
+ 0xf1, 0x2d, 0xb5, 0xde, 0xcf, 0xd0, 0x23, 0x90, 0x4c, 0x35,
+ 0x0b, 0xf1, 0x61, 0xa1, 0xc7, 0xbd, 0x31, 0xf7, 0x78, 0xde,
+ 0x52, 0x3a, 0x9c, 0xda, 0x12, 0x8b, 0xb5, 0xfe, 0x87, 0xf4,
+ 0xf5, 0xb0, 0x1f, 0xdb, 0x49, 0x05, 0xaa, 0xbf, 0x41, 0x16,
+ 0x32, 0x02, 0x73, 0x12, 0x87, 0x9c, 0xfd, 0x19, 0x98, 0xb3,
+ 0x94, 0xbd, 0x51, 0x71, 0xa8, 0x01, 0xb6, 0x8a },
+ { 0x7e, 0x81, 0x13, 0x74, 0x3f, 0x9a, 0xb0, 0x85, 0xac, 0xdd,
+ 0xb6, 0xff, 0x95, 0x1c, 0xa4, 0x9a, 0xe1, 0xc8, 0x35, 0x45,
+ 0x69, 0x80, 0x7b, 0xaa, 0xaf, 0xb6, 0x02, 0x69, 0xff, 0x51,
+ 0xa9, 0xff, 0xfe, 0x6a, 0xd2, 0x2e, 0xf2, 0xd5, 0x73, 0x7c,
+ 0x6b, 0x3f, 0xaa, 0xbe, 0x18, 0x78, 0x97, 0xe0, 0x59, 0x27,
+ 0xdd, 0x51, 0xdc, 0x7c, 0xb4, 0x88, 0x00, 0x26, 0x67, 0x06,
+ 0x4d, 0xf6, 0xc7, 0xd0, 0x2e, 0x42, 0xc3, 0xe1, 0x62, 0xee,
+ 0x7c, 0xc8, 0x76, 0xdd, 0x30, 0x45, 0xa8, 0xb9, 0xa6, 0x57,
+ 0x3f, 0x27, 0x18, 0x54, 0xac, 0x05, 0x45, 0x24, 0x04, 0xc2,
+ 0xbb, 0x36, 0xfa, 0x17, 0xd8, 0x0d, 0x45, 0x5d, 0x18, 0x5c,
+ 0x48, 0x74, 0x91, 0x3d, 0x42, 0x2e, 0x71, 0xf7, 0xfd, 0x60,
+ 0xb5, 0xf8, 0xa5, 0xe7, 0x40, 0xba, 0x45, 0xfb, 0xe5, 0x23,
+ 0x3c, 0xb8, 0x63, 0x89, 0x2a, 0xee, 0xc6, 0x88 },
+ { 0x43, 0x6b, 0x8c, 0x64, 0xdf, 0x84, 0x85, 0xa6, 0x00, 0x1c,
+ 0x79, 0x18, 0xba, 0x56, 0xfa, 0x91, 0x63, 0x76, 0xc1, 0xa2,
+ 0x63, 0xdb, 0x2b, 0xfe, 0xfe, 0x0c, 0x9f, 0x81, 0x39, 0x6d,
+ 0xa4, 0x22, 0xe4, 0x53, 0x86, 0x67, 0x32, 0xa1, 0xad, 0x94,
+ 0x23, 0xe0, 0xb4, 0x6c, 0xae, 0xec, 0x0b, 0xfe, 0x97, 0xd7,
+ 0x1e, 0xff, 0x50, 0x04, 0xf2, 0x86, 0xbb, 0x07, 0x6b, 0x98,
+ 0xe3, 0x91, 0xc0, 0xcd, 0xda, 0x77, 0x4d, 0xe5, 0xf5, 0xff,
+ 0x43, 0xcb, 0x0c, 0x1c, 0x15, 0x5a, 0x23, 0x86, 0xc4, 0x53,
+ 0x98, 0x45, 0xcd, 0x06, 0x15, 0xb0, 0xcd, 0x5e, 0x2f, 0xd0,
+ 0x9d, 0xb0, 0xe5, 0x89, 0x66, 0x9c, 0xb5, 0x38, 0x12, 0xd3,
+ 0x6c, 0x46, 0xd1, 0xd3, 0x3e, 0x02, 0xd0, 0xb8, 0x04, 0x09,
+ 0xb4, 0x7d, 0x91, 0x91, 0x8e, 0xa8, 0xce, 0x11, 0x17, 0xe1,
+ 0xad, 0x72, 0x2a, 0x8b, 0x83, 0x0a, 0x88, 0xb1 },
+ { 0x52, 0x66, 0xca, 0x9e, 0x6d, 0xbe, 0x95, 0xe1, 0x1d, 0xf7,
+ 0xaa, 0xe4, 0x07, 0x68, 0xcb, 0x66, 0x6f, 0x7c, 0x90, 0xe1,
+ 0x53, 0x7d, 0xa5, 0xff, 0xe5, 0xdc, 0xde, 0x62, 0x17, 0x95,
+ 0x44, 0x05, 0x50, 0x60, 0x07, 0x5e, 0x02, 0x43, 0xdc, 0xb6,
+ 0xe5, 0x01, 0x85, 0x17, 0xcd, 0x51, 0xe5, 0x3f, 0xe6, 0x14,
+ 0x14, 0x8e, 0xd4, 0x73, 0x94, 0xa3, 0x79, 0x90, 0x8b, 0x90,
+ 0x8c, 0x92, 0x79, 0x9d, 0xe4, 0xf9, 0xd4, 0x1e, 0x18, 0xd9,
+ 0x70, 0x68, 0xdd, 0x7d, 0x68, 0xc9, 0x43, 0xc8, 0xc2, 0x86,
+ 0x63, 0x3b, 0x95, 0xde, 0xb2, 0x3b, 0x41, 0xdf, 0x01, 0xa5,
+ 0x2e, 0x33, 0x07, 0x1a, 0x34, 0x7a, 0x54, 0x89, 0x16, 0xaf,
+ 0xfc, 0x94, 0x51, 0xdc, 0x5a, 0x77, 0x65, 0xd3, 0x0c, 0x18,
+ 0xee, 0xbd, 0xdf, 0xa6, 0x1e, 0x94, 0xa0, 0x77, 0xdf, 0x84,
+ 0x88, 0x11, 0x7e, 0x9d, 0x8a, 0xb7, 0x64, 0xbc },
+ { 0x41, 0xf3, 0x25, 0xb9, 0x9c, 0xd8, 0x4a, 0x2b, 0xc1, 0x7a,
+ 0x09, 0x20, 0x1f, 0xc6, 0x70, 0x3a, 0x0f, 0x32, 0xb4, 0x49,
+ 0x4f, 0xb4, 0xcb, 0x67, 0xa9, 0x75, 0x04, 0x4e, 0x62, 0x6b,
+ 0xea, 0x27, 0x7d, 0xec, 0x36, 0x2b, 0x7b, 0xd3, 0xe2, 0x20,
+ 0x89, 0x9a, 0x20, 0xb4, 0x14, 0x6e, 0xf8, 0xff, 0x20, 0x7c,
+ 0x13, 0x47, 0x2b, 0x2f, 0x3b, 0xff, 0x6f, 0xb8, 0xcb, 0x1d,
+ 0x14, 0x96, 0x0d, 0x7c, 0xf1, 0xe2, 0x98, 0xfd, 0x94, 0x0c,
+ 0xe1, 0xe8, 0x8f, 0x34, 0xe1, 0x74, 0x86, 0xc3, 0x1f, 0xf0,
+ 0x35, 0x19, 0xc6, 0xe3, 0x19, 0xfd, 0x70, 0xc1, 0x3e, 0x6e,
+ 0x69, 0x24, 0x30, 0x25, 0x7c, 0xfc, 0x21, 0x38, 0xa1, 0xe8,
+ 0xfd, 0xe5, 0xa4, 0xfd, 0xb3, 0x41, 0x84, 0x40, 0xeb, 0x04,
+ 0xf4, 0x9d, 0xf9, 0xe4, 0xaf, 0x5a, 0x7c, 0x38, 0xe5, 0x40,
+ 0x84, 0xdd, 0xee, 0x6d, 0x13, 0x86, 0xb3, 0xdb },
+ { 0x56, 0xb3, 0x0f, 0xb6, 0xe5, 0x8c, 0xea, 0x9e, 0x7d, 0xb3,
+ 0xd3, 0x7b, 0xd9, 0xaa, 0x18, 0xfd, 0x49, 0xef, 0x46, 0x70,
+ 0xeb, 0x8c, 0x34, 0x68, 0x00, 0xf2, 0xe3, 0xac, 0x24, 0x2c,
+ 0xa8, 0xfd, 0x89, 0x47, 0xba, 0x6d, 0x9b, 0xfd, 0x07, 0xdd,
+ 0xc6, 0x47, 0x70, 0x5e, 0xa7, 0x61, 0xba, 0x43, 0x3d, 0xb6,
+ 0xd2, 0x8d, 0x23, 0x40, 0x0a, 0xa7, 0x59, 0x23, 0x52, 0x1f,
+ 0x1d, 0xac, 0x89, 0x44, 0xdf, 0xe2, 0xdc, 0x47, 0xf1, 0x7b,
+ 0x73, 0x41, 0x98, 0x27, 0x6d, 0x96, 0x28, 0x9e, 0x7b, 0xb9,
+ 0x2a, 0x57, 0x8c, 0xb5, 0x06, 0x3e, 0x7b, 0x38, 0x59, 0x05,
+ 0xe1, 0xd9, 0x4b, 0xed, 0x33, 0x8d, 0x34, 0x06, 0x47, 0x04,
+ 0xa6, 0x20, 0x08, 0x3b, 0xa8, 0xef, 0x28, 0x22, 0x4d, 0x86,
+ 0x4c, 0xe5, 0xe7, 0x48, 0x49, 0x8e, 0x00, 0x72, 0x8a, 0xfc,
+ 0x31, 0x2e, 0xd5, 0x13, 0xce, 0x28, 0x43, 0xa4 },
+ { 0x13, 0x53, 0xcc, 0x57, 0x58, 0xbd, 0xd1, 0x46, 0x89, 0x90,
+ 0x81, 0xe5, 0xdc, 0xcf, 0x7f, 0x07, 0xe4, 0x72, 0xfb, 0x8b,
+ 0x17, 0xc0, 0xd9, 0x69, 0x58, 0xf8, 0x8c, 0x51, 0xc6, 0x52,
+ 0x3a, 0x79, 0x3e, 0xdf, 0x81, 0xf5, 0x85, 0xd3, 0xcd, 0x83,
+ 0xde, 0xa9, 0xb4, 0xfa, 0xf8, 0x72, 0x04, 0xae, 0x30, 0x92,
+ 0x23, 0x77, 0x90, 0xbb, 0x1c, 0xd8, 0xc4, 0xe0, 0xb7, 0xf8,
+ 0x94, 0x39, 0x2a, 0x91, 0x78, 0xb6, 0x34, 0xa5, 0xad, 0xe8,
+ 0xa8, 0x8d, 0x0b, 0xfa, 0xef, 0xa5, 0x1f, 0x2f, 0xae, 0xcb,
+ 0xc3, 0x4e, 0x40, 0x75, 0x65, 0xf8, 0x07, 0xd3, 0x21, 0x23,
+ 0x53, 0x3c, 0xb2, 0xe8, 0x1c, 0x3a, 0x3b, 0xed, 0x9a, 0x44,
+ 0x92, 0x4b, 0x00, 0x8a, 0x20, 0xd8, 0x87, 0x98, 0x3a, 0xda,
+ 0x44, 0x1f, 0x7a, 0xf9, 0x22, 0xdc, 0x87, 0x32, 0xc8, 0x91,
+ 0x07, 0xec, 0xdc, 0xaa, 0xcd, 0x80, 0xa4, 0x28 },
+ { 0x3e, 0xc2, 0x18, 0x5d, 0xf4, 0x51, 0xdf, 0x58, 0x72, 0x3a,
+ 0x83, 0x0e, 0x5a, 0x21, 0xe7, 0x89, 0x8d, 0x1d, 0xf4, 0x3c,
+ 0xbb, 0x1c, 0xc1, 0xf1, 0x8f, 0x41, 0x93, 0xa9, 0xa6, 0xb1,
+ 0x6e, 0xbd, 0xbc, 0x69, 0xcf, 0xc0, 0x52, 0x87, 0x7a, 0xe5,
+ 0x75, 0xf4, 0xe5, 0x70, 0xf8, 0xa3, 0x62, 0x35, 0xa5, 0x58,
+ 0xf9, 0x28, 0x15, 0x5c, 0xe6, 0xde, 0x8a, 0x79, 0x7f, 0xc7,
+ 0x95, 0x8d, 0xdb, 0xad, 0x49, 0x68, 0x5d, 0x86, 0xcd, 0x39,
+ 0xe4, 0x2b, 0x84, 0x16, 0xa7, 0xe0, 0x72, 0xd6, 0x72, 0x97,
+ 0xf1, 0x58, 0x3e, 0xd6, 0x27, 0xf8, 0x12, 0x94, 0x2a, 0xb3,
+ 0xa1, 0x64, 0x6a, 0x7b, 0x8e, 0x82, 0xd9, 0x35, 0xbf, 0x51,
+ 0x20, 0x47, 0x04, 0x0c, 0x8d, 0x94, 0x34, 0xa0, 0xdc, 0xe8,
+ 0xb8, 0xe7, 0x59, 0xe8, 0xb5, 0xa2, 0x64, 0x9b, 0x89, 0xc7,
+ 0x28, 0xa5, 0x64, 0x97, 0x39, 0xbf, 0x6e, 0x18 },
+ { 0x89, 0xb3, 0x56, 0xb6, 0xa2, 0x11, 0xab, 0xe5, 0x30, 0x87,
+ 0xdc, 0x5c, 0xe9, 0xd4, 0x47, 0xa3, 0x5f, 0x1d, 0xe8, 0xcc,
+ 0x39, 0xbd, 0xd6, 0x66, 0xbc, 0x93, 0xc5, 0xf3, 0x54, 0x97,
+ 0xaa, 0x72, 0xb5, 0x27, 0xc5, 0x7b, 0x8b, 0xc9, 0x76, 0x07,
+ 0xb4, 0xa6, 0x7a, 0xe7, 0xd3, 0x89, 0x51, 0xe0, 0xb0, 0xd8,
+ 0x4b, 0x1f, 0x8d, 0x7d, 0x43, 0x29, 0x8e, 0x40, 0x61, 0x21,
+ 0x06, 0xbc, 0x05, 0x50, 0xba, 0x18, 0x8c, 0x56, 0x7b, 0xc2,
+ 0x8b, 0x9d, 0x60, 0x24, 0x2a, 0xcb, 0x12, 0xf0, 0xd2, 0xc8,
+ 0x69, 0xd4, 0x9c, 0xe1, 0xc7, 0x78, 0x50, 0xbe, 0x35, 0x03,
+ 0x14, 0x9f, 0x37, 0xf3, 0x51, 0xf9, 0xb7, 0xdd, 0x2d, 0x25,
+ 0x04, 0x7a, 0xe0, 0x9c, 0x92, 0xe0, 0x2d, 0x93, 0xa0, 0x9f,
+ 0x80, 0xf6, 0x69, 0x82, 0xc6, 0xcc, 0x6e, 0x51, 0xd4, 0x12,
+ 0xb9, 0xd4, 0xc7, 0xd7, 0x1f, 0x0b, 0xc2, 0xd7 },
+ { 0x39, 0xc4, 0xf1, 0x0d, 0x57, 0xc5, 0xd1, 0x26, 0x65, 0x6f,
+ 0x18, 0xe0, 0x8a, 0x0d, 0x4f, 0x52, 0x7e, 0x12, 0x02, 0xbe,
+ 0x87, 0xad, 0xc2, 0xf9, 0x4e, 0xf3, 0xa8, 0x0e, 0xdc, 0x60,
+ 0xee, 0xe5, 0x2c, 0xc2, 0x7c, 0xef, 0x00, 0xbf, 0x79, 0x28,
+ 0xe1, 0xbb, 0x97, 0x02, 0x55, 0x84, 0xbc, 0x86, 0x9c, 0xf5,
+ 0x81, 0x7f, 0x87, 0x64, 0x86, 0x43, 0x01, 0x16, 0x19, 0xc9,
+ 0xcb, 0x16, 0x2d, 0xc2, 0xee, 0x62, 0x8e, 0xce, 0xf4, 0x26,
+ 0xda, 0xea, 0x63, 0xe1, 0x1d, 0x26, 0x37, 0x43, 0x36, 0x58,
+ 0x11, 0xb0, 0x4f, 0x72, 0x0e, 0x41, 0xd9, 0x4e, 0x56, 0x64,
+ 0xa2, 0xda, 0x8b, 0x86, 0x57, 0xa3, 0xf5, 0xb5, 0x6b, 0xf7,
+ 0xad, 0xac, 0x9e, 0x5c, 0x41, 0x3a, 0xbf, 0xc9, 0x1c, 0x1d,
+ 0x4b, 0x72, 0x0f, 0xb8, 0x0b, 0xaa, 0xa8, 0x71, 0xb7, 0xa9,
+ 0xed, 0x6d, 0xb0, 0xaf, 0xdf, 0xdc, 0xc8, 0x37 },
+ { 0x41, 0x4b, 0x54, 0x2d, 0x49, 0x15, 0x2b, 0x00, 0xcf, 0xf1,
+ 0x64, 0x78, 0x90, 0x69, 0xfb, 0xcc, 0x0b, 0x9a, 0x17, 0x07,
+ 0xb6, 0xe5, 0x79, 0xcf, 0x44, 0xc6, 0xc9, 0x77, 0x5a, 0xed,
+ 0x24, 0xc4, 0xfd, 0xe5, 0xbe, 0x8d, 0x73, 0xf7, 0xe3, 0x39,
+ 0x28, 0x17, 0xeb, 0xb3, 0xd4, 0x6f, 0xf5, 0x1b, 0xbe, 0xc7,
+ 0x76, 0x7e, 0xc7, 0xd4, 0xc5, 0x56, 0xf2, 0xb6, 0x37, 0x25,
+ 0xf1, 0xaa, 0x12, 0x02, 0xa7, 0xbc, 0x17, 0x75, 0x89, 0x4c,
+ 0x44, 0x44, 0xc8, 0x41, 0xe9, 0xea, 0x3b, 0xd1, 0x62, 0x83,
+ 0x6d, 0x1e, 0x6d, 0x35, 0xa8, 0x1a, 0x0a, 0x78, 0x7d, 0xac,
+ 0x80, 0xd0, 0x81, 0x1a, 0xc7, 0x2d, 0x79, 0xb6, 0x8b, 0x67,
+ 0x02, 0x06, 0x8d, 0x84, 0xed, 0xc1, 0xcd, 0xad, 0x4b, 0xd4,
+ 0xee, 0x54, 0x55, 0x5b, 0x09, 0x18, 0xa5, 0x18, 0xaa, 0x9d,
+ 0xb3, 0xa9, 0xb6, 0x8c, 0xe8, 0x8a, 0xec, 0xd3 },
+ { 0x52, 0x67, 0x8d, 0x6a, 0xe0, 0x0b, 0x8b, 0x2a, 0x43, 0x97,
+ 0x78, 0x74, 0x44, 0x4e, 0x85, 0x15, 0x3c, 0x73, 0x62, 0xfa,
+ 0x96, 0x08, 0xf5, 0xbf, 0xf4, 0x8e, 0x62, 0x3e, 0x27, 0x0d,
+ 0x17, 0xa6, 0x13, 0x33, 0x8e, 0xf8, 0xed, 0x55, 0x6a, 0x6c,
+ 0x74, 0xab, 0x92, 0x48, 0xd1, 0x84, 0x30, 0x07, 0xaf, 0x1f,
+ 0x4a, 0x6e, 0x74, 0x0d, 0xb2, 0x9c, 0xb2, 0xe4, 0xd6, 0x6c,
+ 0x1b, 0xa2, 0xae, 0xa9, 0x70, 0x8f, 0x9b, 0x32, 0x44, 0xaf,
+ 0x08, 0x2e, 0xe1, 0x31, 0xe8, 0x8f, 0x94, 0x50, 0x69, 0x0a,
+ 0x9f, 0x9d, 0x35, 0xac, 0x81, 0xc6, 0xe6, 0xd7, 0x3e, 0xf0,
+ 0x56, 0x02, 0x90, 0x13, 0xe4, 0xec, 0xc7, 0x88, 0xc6, 0x17,
+ 0x05, 0x12, 0x0e, 0x70, 0x42, 0x5f, 0xb5, 0x12, 0xde, 0xbb,
+ 0x20, 0xaf, 0x5b, 0x7f, 0x4e, 0x1b, 0x90, 0xe6, 0x71, 0x3a,
+ 0x33, 0xc3, 0x1e, 0x58, 0x60, 0x6e, 0x17, 0x3b },
+ { 0x70, 0x40, 0xba, 0x5b, 0xc1, 0x0c, 0xee, 0xdd, 0x04, 0x5a,
+ 0xc6, 0x14, 0xc8, 0xef, 0xce, 0xa6, 0x23, 0xa5, 0x9c, 0x1d,
+ 0xbf, 0x22, 0xf6, 0x82, 0xb8, 0xee, 0x84, 0x2a, 0x5d, 0x99,
+ 0x74, 0xc9, 0x4b, 0x58, 0xf9, 0xb2, 0xd3, 0x05, 0x3b, 0x4f,
+ 0x3e, 0xcd, 0x40, 0x75, 0x0f, 0x79, 0x48, 0xa9, 0x0e, 0x41,
+ 0x19, 0x6e, 0xf6, 0xd2, 0xd7, 0xff, 0xf3, 0x9c, 0x49, 0x0e,
+ 0x5a, 0xa5, 0x69, 0x5c, 0xfa, 0xb4, 0x18, 0xd3, 0x2c, 0x1b,
+ 0xf9, 0x06, 0x1a, 0x33, 0xe9, 0x4f, 0x3f, 0x7d, 0x9e, 0x09,
+ 0x2b, 0xd6, 0x18, 0x04, 0x93, 0x33, 0x44, 0x85, 0x25, 0x8c,
+ 0x2c, 0x52, 0xa5, 0x71, 0xf8, 0x9b, 0x85, 0x09, 0xd4, 0x14,
+ 0x2d, 0xfd, 0x49, 0x1f, 0x0e, 0x03, 0xf4, 0x96, 0x92, 0x7a,
+ 0x5f, 0x81, 0x52, 0xd6, 0x65, 0x3c, 0xa9, 0x2b, 0xc0, 0xab,
+ 0x5d, 0xff, 0x1c, 0x59, 0xdf, 0x36, 0xae, 0xb4 },
+ { 0x90, 0x43, 0xa6, 0xd6, 0x0b, 0xd1, 0xc9, 0xc1, 0x3d, 0x28,
+ 0x1e, 0x1a, 0xfe, 0x87, 0x32, 0x48, 0xff, 0x2d, 0xff, 0x4e,
+ 0x70, 0xf4, 0xea, 0xa3, 0xfa, 0xc3, 0xe5, 0x82, 0x43, 0x65,
+ 0x78, 0x4a, 0x97, 0xd2, 0xb7, 0x21, 0xb7, 0x74, 0xc3, 0x1e,
+ 0xaf, 0x9a, 0x23, 0xe8, 0xe7, 0xe3, 0x86, 0x0e, 0xc1, 0xfe,
+ 0x0d, 0x8a, 0xde, 0x1d, 0x33, 0x6f, 0x65, 0x27, 0x34, 0x9f,
+ 0xfb, 0x29, 0x4c, 0x4a, 0x2f, 0xd4, 0xf0, 0xc6, 0x5b, 0x25,
+ 0xf0, 0x06, 0x34, 0x92, 0x27, 0x6b, 0x86, 0x67, 0x69, 0x6b,
+ 0x1e, 0x01, 0xa7, 0x42, 0x28, 0x14, 0xc1, 0x77, 0x88, 0x86,
+ 0xd8, 0x76, 0xd2, 0xcd, 0xa9, 0xd2, 0x9d, 0x76, 0x94, 0xf1,
+ 0x27, 0x3b, 0x61, 0x73, 0x0a, 0x09, 0x66, 0x50, 0x1a, 0xd9,
+ 0x3d, 0x4f, 0x31, 0xa6, 0x35, 0x03, 0x18, 0x43, 0x27, 0xe0,
+ 0x2c, 0x36, 0x4f, 0x81, 0x51, 0x5a, 0x1a, 0x96 },
+ { 0x26, 0x36, 0x2b, 0x48, 0x3a, 0x12, 0x5f, 0x35, 0xb0, 0x76,
+ 0x0a, 0x3c, 0xb7, 0x3e, 0xac, 0x46, 0xe4, 0x5c, 0x75, 0xdf,
+ 0xff, 0xaa, 0xd0, 0x78, 0x7b, 0xd2, 0xc1, 0x38, 0x1e, 0x35,
+ 0x79, 0xb2, 0x95, 0x77, 0x1f, 0xa2, 0xdb, 0x4e, 0x80, 0x1a,
+ 0x79, 0xbc, 0x85, 0xc6, 0x4e, 0x8d, 0xa1, 0x54, 0x2c, 0x8d,
+ 0x38, 0x34, 0x40, 0xc9, 0x2a, 0xf9, 0xfb, 0x12, 0xea, 0x4d,
+ 0xf5, 0x97, 0xf6, 0x63, 0xc3, 0xc3, 0x46, 0x3a, 0xe4, 0x06,
+ 0x98, 0x80, 0x99, 0x6b, 0x08, 0x22, 0xce, 0xdf, 0xcd, 0x94,
+ 0x8a, 0xd7, 0xa0, 0x3a, 0x9c, 0xbe, 0x10, 0x6f, 0xb8, 0x01,
+ 0xc8, 0x3d, 0x34, 0xa2, 0xea, 0x06, 0x92, 0x87, 0x54, 0xbd,
+ 0x61, 0x62, 0x00, 0xf3, 0x2a, 0xc1, 0x60, 0xcc, 0xe0, 0x08,
+ 0x88, 0xac, 0x1b, 0x2d, 0xed, 0x5c, 0xab, 0xbc, 0x3b, 0xe3,
+ 0x15, 0x11, 0xa0, 0xfe, 0x76, 0x6c, 0x79, 0x37 },
+ { 0x2e, 0x95, 0x2b, 0x20, 0x55, 0x5c, 0x93, 0x5e, 0x45, 0x2f,
+ 0xe2, 0x31, 0x09, 0xff, 0x59, 0xba, 0x9c, 0x86, 0xe0, 0xb2,
+ 0x96, 0xc6, 0xb5, 0xee, 0x92, 0xc2, 0x65, 0x63, 0xc1, 0x43,
+ 0x92, 0x73, 0x5a, 0xce, 0x53, 0xd1, 0xbe, 0xe0, 0xf2, 0xe9,
+ 0x19, 0x3f, 0x88, 0xc8, 0x05, 0x4d, 0x54, 0x71, 0x7b, 0x60,
+ 0xd4, 0x64, 0xa7, 0xbf, 0x21, 0xda, 0x45, 0xe4, 0xf2, 0xa5,
+ 0xbe, 0xa9, 0xcd, 0x49, 0x21, 0xfb, 0xd3, 0x10, 0x1e, 0x06,
+ 0xd4, 0x85, 0x39, 0x1f, 0x68, 0x8a, 0x44, 0xf9, 0x71, 0x45,
+ 0xa5, 0xee, 0xb2, 0xb1, 0x4c, 0x0d, 0xa1, 0xe9, 0xfd, 0x3d,
+ 0x20, 0xea, 0xff, 0x55, 0x2b, 0xac, 0xdb, 0x70, 0x90, 0x72,
+ 0xcb, 0x86, 0xb3, 0x33, 0x8b, 0x07, 0xbb, 0x86, 0xaf, 0x5e,
+ 0x4b, 0x75, 0x2d, 0x0e, 0xe8, 0x77, 0x69, 0xe9, 0xee, 0x71,
+ 0x25, 0xc6, 0x8d, 0x28, 0xee, 0xfc, 0x3e, 0x89 },
+ { 0x12, 0x36, 0xd0, 0x17, 0x30, 0x37, 0x8e, 0x4b, 0x1c, 0x0a,
+ 0x84, 0xc9, 0xeb, 0x53, 0xef, 0x06, 0xa5, 0xc1, 0x48, 0x96,
+ 0xdb, 0x2f, 0x02, 0x73, 0x2b, 0xcd, 0x96, 0xb0, 0xb0, 0x93,
+ 0x77, 0xe0, 0xff, 0x60, 0x4a, 0x11, 0x17, 0x55, 0x9a, 0x30,
+ 0x7c, 0x14, 0xef, 0x33, 0x53, 0xb1, 0xfa, 0x97, 0x7a, 0xaa,
+ 0x53, 0xf2, 0xa4, 0x4d, 0x2f, 0xa8, 0x8e, 0xf8, 0x3f, 0xb3,
+ 0x9d, 0x6e, 0xbc, 0xb1, 0xa5, 0xc2, 0x6e, 0x3a, 0x7f, 0xbd,
+ 0x85, 0x6d, 0x02, 0x51, 0x13, 0xec, 0x6c, 0x12, 0x20, 0x76,
+ 0x28, 0x35, 0xb3, 0x86, 0x18, 0x1e, 0x5e, 0x33, 0xbc, 0x70,
+ 0x2f, 0x26, 0xa2, 0x63, 0xec, 0xc9, 0x58, 0x0e, 0x2e, 0xc9,
+ 0x35, 0x5f, 0xf2, 0xb5, 0x10, 0x3e, 0x45, 0xb6, 0x00, 0x7b,
+ 0x1b, 0x86, 0xe6, 0x8a, 0x5d, 0xbe, 0xd4, 0x3d, 0xfc, 0x58,
+ 0x2a, 0x84, 0x6b, 0xca, 0xd7, 0x5f, 0x88, 0x6e },
+ { 0x02, 0xa4, 0x80, 0x14, 0x62, 0x0c, 0xb5, 0x6e, 0x35, 0x3c,
+ 0x2d, 0x85, 0x4b, 0x9e, 0xc7, 0xea, 0xe6, 0x16, 0xf5, 0x55,
+ 0x6c, 0x97, 0xf0, 0xe9, 0x19, 0x88, 0x19, 0x41, 0xd1, 0x46,
+ 0x58, 0xf3, 0xb3, 0xfc, 0xd3, 0x65, 0x24, 0x38, 0x90, 0x6d,
+ 0xbb, 0x0c, 0x5d, 0x66, 0x74, 0xcc, 0x95, 0xcb, 0x7d, 0x2c,
+ 0x72, 0x7d, 0xba, 0x75, 0x30, 0xe9, 0x3b, 0xdd, 0xe1, 0xa8,
+ 0x70, 0x6e, 0xf8, 0x17, 0x65, 0xba, 0xf5, 0x94, 0x33, 0x0a,
+ 0x32, 0x82, 0xf0, 0xec, 0x0b, 0x38, 0x42, 0x31, 0x45, 0x76,
+ 0x55, 0x4f, 0xbb, 0x9f, 0xed, 0x01, 0x08, 0x00, 0x86, 0x52,
+ 0x46, 0x29, 0x0e, 0x2b, 0xe7, 0xe2, 0x37, 0x12, 0x71, 0x4c,
+ 0x93, 0x4b, 0xc2, 0xb0, 0x13, 0x00, 0xdf, 0xa0, 0x61, 0x3b,
+ 0xc3, 0x4b, 0x29, 0xae, 0x47, 0x68, 0x64, 0x60, 0x97, 0xae,
+ 0xd7, 0x48, 0x1c, 0x8f, 0xc0, 0x84, 0x37, 0x3b },
+ { 0x1d, 0x8b, 0xde, 0x6f, 0x8f, 0x21, 0x7f, 0xe0, 0x31, 0x39,
+ 0x04, 0x14, 0xb5, 0x5f, 0x75, 0xf3, 0xa4, 0x4e, 0x2c, 0x25,
+ 0xc3, 0x55, 0x6d, 0x18, 0xbe, 0x2d, 0xa8, 0x87, 0xa2, 0xe8,
+ 0xc3, 0xda, 0x43, 0x04, 0x46, 0x60, 0x91, 0xeb, 0x25, 0x99,
+ 0x19, 0x2a, 0x64, 0xb7, 0x36, 0x9f, 0x46, 0xc7, 0x32, 0x39,
+ 0x5d, 0xee, 0x1e, 0x01, 0x14, 0xde, 0xee, 0x95, 0x7c, 0x67,
+ 0x49, 0xfc, 0xb8, 0x80, 0xde, 0xc0, 0xff, 0xbf, 0x8e, 0xc9,
+ 0x55, 0xfd, 0x99, 0xab, 0x26, 0xbd, 0x9f, 0x15, 0x4d, 0x1f,
+ 0xf0, 0xa7, 0xb4, 0x27, 0xaa, 0xda, 0xc2, 0x58, 0xf5, 0xd6,
+ 0x3b, 0xbb, 0x83, 0x83, 0x50, 0x83, 0xe8, 0x7e, 0x1b, 0x46,
+ 0xd8, 0x28, 0x93, 0x7d, 0x71, 0x7c, 0x9c, 0x27, 0x69, 0xd0,
+ 0x11, 0xc5, 0x22, 0x9a, 0x1c, 0x54, 0x90, 0x59, 0xba, 0xa6,
+ 0x11, 0xd6, 0xd2, 0x3d, 0x50, 0x6c, 0xcd, 0x38 },
+ { 0x34, 0x9c, 0x69, 0x43, 0xc6, 0x10, 0x13, 0xc1, 0xf5, 0x65,
+ 0xb2, 0x8b, 0xcc, 0x83, 0x20, 0x9e, 0xb3, 0x6e, 0xd3, 0x5c,
+ 0xde, 0xb9, 0x3b, 0x87, 0xb9, 0xb0, 0x0a, 0x02, 0x36, 0x0d,
+ 0x3a, 0x26, 0xdc, 0x37, 0x5c, 0x84, 0xee, 0x8d, 0x21, 0x39,
+ 0xd8, 0x19, 0x6b, 0x5b, 0xb6, 0xfc, 0x65, 0x5a, 0x74, 0xfc,
+ 0x2a, 0x6a, 0xbf, 0xb1, 0x76, 0x38, 0x79, 0x93, 0xf5, 0x7a,
+ 0xac, 0x94, 0xd4, 0xd1, 0x59, 0x4d, 0x4d, 0x43, 0xf8, 0x8b,
+ 0x05, 0xe6, 0x41, 0x4d, 0xec, 0xcb, 0xa6, 0x72, 0xba, 0x38,
+ 0xf4, 0x21, 0x38, 0x26, 0x6f, 0x1b, 0xb6, 0x5c, 0x93, 0x97,
+ 0xc9, 0x7a, 0xb1, 0x0f, 0xec, 0x10, 0xdb, 0xe0, 0x67, 0x16,
+ 0x5a, 0x06, 0x07, 0x76, 0x86, 0x2b, 0xbc, 0xb7, 0xd6, 0xf0,
+ 0x58, 0x46, 0x6e, 0x54, 0xf1, 0x9c, 0xb0, 0x6e, 0xcb, 0x9f,
+ 0x03, 0xcd, 0x39, 0xf8, 0xa2, 0x02, 0x89, 0x24 },
+ { 0x05, 0x65, 0x87, 0xab, 0x89, 0xc2, 0xd8, 0xfa, 0xa3, 0x2f,
+ 0x32, 0x7e, 0x87, 0x25, 0x57, 0x69, 0x21, 0x19, 0x52, 0x99,
+ 0x08, 0x17, 0xc5, 0xc2, 0x9c, 0xf8, 0x42, 0xd5, 0x27, 0x18,
+ 0x2a, 0xc9, 0xd0, 0xd3, 0xa1, 0x77, 0x07, 0x38, 0x96, 0x35,
+ 0x96, 0x08, 0x9e, 0x8a, 0x5f, 0x0e, 0x12, 0x9b, 0x3a, 0x7f,
+ 0x3e, 0x90, 0xf4, 0xbd, 0x1f, 0x91, 0xc9, 0x91, 0xf1, 0xc7,
+ 0xed, 0x0b, 0xd5, 0x0a, 0x24, 0x3a, 0x66, 0x6e, 0x53, 0x37,
+ 0xf4, 0x53, 0xc5, 0xa8, 0xe2, 0xec, 0x21, 0x46, 0x7e, 0xbf,
+ 0x2d, 0x74, 0x29, 0x38, 0x73, 0x7c, 0x70, 0xf0, 0x40, 0x0b,
+ 0xa5, 0x79, 0xba, 0xef, 0x0c, 0x18, 0x74, 0x9f, 0x75, 0x64,
+ 0x08, 0x50, 0x99, 0x3e, 0xb6, 0xf4, 0x58, 0xa2, 0x21, 0xc2,
+ 0xb7, 0x80, 0xd5, 0xc2, 0xc4, 0x71, 0x47, 0x00, 0x20, 0x7e,
+ 0xd1, 0xb3, 0x94, 0x44, 0x4d, 0xe6, 0xc8, 0x8a },
+ { 0x1b, 0x87, 0xf2, 0xed, 0xb8, 0x6c, 0xdb, 0xde, 0x81, 0x5f,
+ 0x15, 0x65, 0x3f, 0x1d, 0x0f, 0x6c, 0xc4, 0x38, 0x76, 0x4b,
+ 0xf6, 0xca, 0xae, 0x00, 0x63, 0xd0, 0xa0, 0xe9, 0x0f, 0xb1,
+ 0x54, 0x38, 0x6f, 0x3c, 0x0d, 0x68, 0x88, 0x3e, 0x09, 0x72,
+ 0x58, 0xfd, 0x14, 0x37, 0x6f, 0xff, 0x25, 0x4f, 0xc2, 0xca,
+ 0xee, 0x3f, 0x31, 0x90, 0xb5, 0x1e, 0xc2, 0xa8, 0x9e, 0x9f,
+ 0xc4, 0x05, 0x2e, 0xe1, 0xc4, 0xad, 0x91, 0x8f, 0x7e, 0x87,
+ 0x2a, 0xbb, 0x0e, 0x5b, 0x34, 0xd8, 0x9b, 0xd2, 0x70, 0x3e,
+ 0x6b, 0xe8, 0x4c, 0x8f, 0x2a, 0xc2, 0xd2, 0xf6, 0x57, 0xc9,
+ 0x50, 0x36, 0x36, 0xb3, 0x59, 0x76, 0x89, 0x49, 0x4c, 0x5e,
+ 0xb6, 0x1a, 0x8c, 0x13, 0x5f, 0x03, 0x02, 0x1f, 0xa9, 0xab,
+ 0x46, 0xb9, 0x5f, 0xaf, 0xf7, 0xcb, 0x98, 0xe5, 0x14, 0x44,
+ 0x00, 0x85, 0x62, 0xed, 0x1c, 0xe4, 0x73, 0x3d },
+ { 0x8e, 0x02, 0x27, 0xc4, 0x3e, 0x95, 0xbc, 0x23, 0xb2, 0x2b,
+ 0x87, 0xb1, 0xc4, 0xa3, 0xe5, 0x9e, 0xbe, 0x3f, 0x3c, 0x77,
+ 0x88, 0x84, 0x8a, 0x99, 0x37, 0x4b, 0xf4, 0x16, 0x97, 0x12,
+ 0xa0, 0xca, 0xe2, 0x43, 0x0d, 0xe8, 0xed, 0xfc, 0xa0, 0xcc,
+ 0x8d, 0xf9, 0xcb, 0x47, 0x7e, 0xb8, 0x05, 0x6d, 0x87, 0xb9,
+ 0xb9, 0x4d, 0x39, 0x63, 0x29, 0x90, 0x4d, 0x62, 0x1e, 0x73,
+ 0xba, 0x32, 0x23, 0xa3, 0xb0, 0x50, 0x79, 0x1e, 0x7a, 0xa8,
+ 0xcc, 0x54, 0xce, 0x3e, 0x84, 0xe0, 0x2d, 0x10, 0x52, 0xc2,
+ 0x07, 0x70, 0xf0, 0x7a, 0x95, 0xd6, 0x80, 0x66, 0x0e, 0x3f,
+ 0x55, 0x56, 0xc4, 0x70, 0x31, 0xc6, 0x00, 0x54, 0x50, 0xbd,
+ 0xc2, 0x98, 0xd1, 0xef, 0xfb, 0xac, 0xff, 0xd9, 0xdd, 0x8f,
+ 0x37, 0x79, 0xa3, 0xe4, 0xb5, 0xa7, 0xce, 0x6b, 0xa7, 0x79,
+ 0x35, 0x79, 0x2b, 0xbb, 0x2b, 0x0b, 0x15, 0xb1 },
+ { 0x14, 0xb1, 0x5a, 0xb5, 0x40, 0x54, 0x5d, 0x6e, 0x84, 0x8e,
+ 0xcb, 0x11, 0x4e, 0xa2, 0x06, 0xbc, 0x52, 0x8e, 0x59, 0x93,
+ 0x53, 0x94, 0xe9, 0x50, 0x5e, 0x9a, 0x26, 0xd3, 0x38, 0xa0,
+ 0x84, 0xdb, 0x3a, 0x3c, 0x16, 0xb3, 0xbd, 0xa9, 0xf3, 0x06,
+ 0xb3, 0xae, 0x38, 0x99, 0x4b, 0x7e, 0xf0, 0xe2, 0xc6, 0xf9,
+ 0xdd, 0x0d, 0xa6, 0x16, 0x5e, 0x5d, 0x22, 0x8a, 0x46, 0xe4,
+ 0x37, 0x8c, 0x26, 0x1d, 0xb9, 0x8e, 0xce, 0x1b, 0x0c, 0x1a,
+ 0x8d, 0xeb, 0xd0, 0x0e, 0x60, 0x3a, 0xbb, 0x3f, 0x82, 0x98,
+ 0x86, 0xec, 0xa7, 0x14, 0x32, 0x24, 0xb4, 0xf5, 0x1c, 0xc5,
+ 0x74, 0xcb, 0x8b, 0xdc, 0xc9, 0x0c, 0xd0, 0x28, 0x33, 0xe0,
+ 0x67, 0xcd, 0xca, 0xe3, 0x02, 0x17, 0x3a, 0x1f, 0xda, 0xf1,
+ 0xea, 0xd7, 0xdc, 0xcd, 0x5d, 0xf5, 0xff, 0x05, 0x6e, 0xeb,
+ 0x00, 0x0e, 0x22, 0xa8, 0x32, 0x10, 0x96, 0x4d },
+ { 0x74, 0x2b, 0xbe, 0xd8, 0xc4, 0x38, 0x9e, 0x2e, 0x1e, 0x16,
+ 0xac, 0x76, 0x00, 0x9a, 0x55, 0xf5, 0xce, 0x57, 0xe1, 0xca,
+ 0x61, 0x2b, 0x57, 0x1f, 0xcb, 0xba, 0x6e, 0x30, 0x47, 0xea,
+ 0x72, 0x2f, 0xdf, 0x20, 0xe0, 0xe9, 0x4b, 0x63, 0xd7, 0x01,
+ 0xdb, 0xee, 0x97, 0xa8, 0x18, 0xfb, 0xf9, 0xfa, 0xca, 0x88,
+ 0x95, 0x3d, 0x60, 0x94, 0x76, 0x3c, 0xcc, 0x89, 0x6a, 0xe7,
+ 0x29, 0x2e, 0x9d, 0x87, 0xd6, 0xf1, 0x8d, 0x2f, 0x3f, 0x09,
+ 0xb4, 0xee, 0xc0, 0xad, 0x9f, 0xfa, 0xc8, 0x7b, 0x28, 0xe1,
+ 0xa4, 0xee, 0x0d, 0xef, 0x0d, 0x5d, 0x4e, 0x05, 0x79, 0xa0,
+ 0xd4, 0xe7, 0x45, 0x87, 0x08, 0x0b, 0x5f, 0x23, 0x25, 0xd9,
+ 0x81, 0x76, 0xa7, 0xe0, 0x33, 0xf9, 0xb5, 0x69, 0x90, 0x72,
+ 0xcb, 0x8e, 0x3d, 0xfe, 0x2b, 0xe1, 0x60, 0xfd, 0x7a, 0xa5,
+ 0x0f, 0x6d, 0x86, 0xc9, 0x66, 0x4c, 0x59, 0xa2 },
+ { 0x97, 0xbd, 0x5a, 0x14, 0xb5, 0xc9, 0x41, 0x24, 0x15, 0x1e,
+ 0x33, 0x08, 0xf7, 0xcd, 0xd6, 0x9b, 0x71, 0x7d, 0x1c, 0xe6,
+ 0xe1, 0xec, 0xc1, 0x7c, 0xb3, 0x90, 0x8b, 0xbf, 0xb8, 0x65,
+ 0xc7, 0xf9, 0xb6, 0xbc, 0x34, 0xe8, 0x7d, 0x11, 0xe4, 0x15,
+ 0xed, 0x8b, 0x3d, 0xfe, 0xeb, 0x8f, 0xe0, 0xc9, 0xe6, 0xc3,
+ 0x5b, 0xb3, 0x4b, 0x18, 0x7c, 0x7d, 0x4c, 0x82, 0x60, 0x57,
+ 0x46, 0xe2, 0xa2, 0x78, 0xc8, 0xc2, 0xe0, 0x2d, 0x1f, 0x72,
+ 0xe0, 0x11, 0x4d, 0x88, 0xd5, 0x40, 0xe3, 0x64, 0xab, 0x94,
+ 0x78, 0x9d, 0xba, 0x22, 0xa9, 0xb7, 0xad, 0x78, 0x7d, 0x54,
+ 0xc6, 0x4b, 0x54, 0xe6, 0x6a, 0x7d, 0xde, 0x68, 0xa6, 0xe0,
+ 0x8c, 0xb5, 0xca, 0xc7, 0x07, 0xf8, 0xfa, 0x1f, 0x24, 0xd8,
+ 0xca, 0x1f, 0x4b, 0xbb, 0xfd, 0x5b, 0xc1, 0x64, 0x3a, 0xbf,
+ 0x23, 0xea, 0x86, 0xdc, 0xc1, 0xdc, 0x2c, 0x73 },
+ { 0x31, 0x7c, 0x6d, 0x31, 0x48, 0xcc, 0x54, 0x69, 0xf8, 0x92,
+ 0xc5, 0x8c, 0x86, 0x4f, 0xba, 0x2e, 0x50, 0xf5, 0x3b, 0xe4,
+ 0xa6, 0x42, 0x4c, 0x2a, 0x4d, 0x63, 0x36, 0x7a, 0xff, 0xab,
+ 0xda, 0x18, 0xf0, 0x53, 0xe8, 0x48, 0x0c, 0xec, 0x8b, 0x9a,
+ 0xb0, 0xd9, 0xb9, 0xba, 0x26, 0xf8, 0x30, 0x5f, 0x03, 0x89,
+ 0xbb, 0xd8, 0xca, 0x60, 0x13, 0xc3, 0xaf, 0x77, 0xd2, 0xd1,
+ 0x0a, 0x8a, 0x0a, 0xf4, 0x52, 0xe8, 0x4c, 0x5f, 0xa2, 0x0c,
+ 0x8b, 0x96, 0x9d, 0xf7, 0x6b, 0x9b, 0x58, 0x2d, 0xe7, 0x5f,
+ 0xce, 0x84, 0x35, 0xa8, 0x55, 0x0f, 0x29, 0xd8, 0xb4, 0xf1,
+ 0x5f, 0x52, 0xc7, 0x2a, 0x45, 0xf4, 0xb8, 0xb4, 0x93, 0x74,
+ 0x5a, 0xbb, 0xbf, 0xdd, 0x7e, 0x52, 0xe5, 0x5b, 0xe6, 0x5e,
+ 0x91, 0xe5, 0x70, 0x3d, 0x4b, 0x6d, 0xdd, 0x42, 0xc4, 0x0e,
+ 0xe0, 0x1c, 0x62, 0xfe, 0x81, 0xe8, 0x28, 0x61 },
+ { 0x6a, 0xe5, 0x97, 0x39, 0x9d, 0xa0, 0xb8, 0xfd, 0x45, 0x16,
+ 0x51, 0xf0, 0xee, 0x3d, 0x3f, 0x17, 0x9c, 0xc3, 0x48, 0x3c,
+ 0x1d, 0x90, 0x63, 0x0b, 0x37, 0x69, 0x79, 0x6a, 0xc2, 0x76,
+ 0x3c, 0x30, 0x49, 0x02, 0x22, 0x79, 0x52, 0x5f, 0x86, 0x36,
+ 0xf9, 0xd7, 0x06, 0x41, 0xec, 0xcb, 0xc1, 0x1c, 0xfc, 0x1a,
+ 0xe3, 0xf5, 0xef, 0xbe, 0x40, 0x08, 0x6d, 0xb9, 0x6d, 0x16,
+ 0xdc, 0x3f, 0x49, 0xda, 0xe9, 0xa1, 0xd2, 0x7f, 0x02, 0x2d,
+ 0xe1, 0x81, 0x59, 0xaf, 0xce, 0x48, 0x11, 0x0e, 0x0d, 0x6e,
+ 0xa0, 0x14, 0x6b, 0x5a, 0x41, 0x25, 0x2a, 0x19, 0x7f, 0xbe,
+ 0xf6, 0x8a, 0x71, 0x8e, 0xb2, 0x3d, 0x6b, 0x01, 0x40, 0x2f,
+ 0xe0, 0xc1, 0x0e, 0xa0, 0x8d, 0x5d, 0x20, 0x22, 0xff, 0x20,
+ 0x40, 0x8f, 0x55, 0x24, 0x0b, 0xc9, 0x31, 0x0f, 0xac, 0xae,
+ 0x0c, 0x35, 0x25, 0xb0, 0x2c, 0xb7, 0xd4, 0x2b },
+ { 0x66, 0x49, 0x04, 0x8d, 0xbc, 0x63, 0xfe, 0x72, 0xa8, 0x4e,
+ 0xe5, 0xf1, 0xe7, 0x44, 0xb8, 0x2b, 0x9e, 0xf9, 0xcf, 0x3e,
+ 0xf1, 0x51, 0xa7, 0x26, 0x8a, 0x85, 0x95, 0xb2, 0xfa, 0x2a,
+ 0xff, 0xfc, 0x8f, 0xe7, 0x3b, 0xff, 0x97, 0xb6, 0x49, 0x7e,
+ 0x28, 0x88, 0x05, 0x34, 0xd3, 0x46, 0xf2, 0x14, 0x1a, 0x89,
+ 0xae, 0x22, 0xd6, 0xcf, 0x00, 0x7a, 0xb0, 0xff, 0x72, 0x26,
+ 0x2d, 0x97, 0xa7, 0x74, 0xee, 0x26, 0x1f, 0xb1, 0x5a, 0x2a,
+ 0xfa, 0x4c, 0xc5, 0x64, 0x86, 0x1f, 0xfd, 0x5f, 0x87, 0xb7,
+ 0xcf, 0x2c, 0x5b, 0x59, 0x8e, 0x61, 0xf9, 0x44, 0xc0, 0x6f,
+ 0x4a, 0x85, 0x4e, 0x0c, 0x33, 0x89, 0x1d, 0x5f, 0x23, 0x2a,
+ 0x5e, 0xfd, 0x55, 0xbe, 0xb6, 0x25, 0x4b, 0xd5, 0x07, 0x94,
+ 0x93, 0x6c, 0x20, 0x75, 0x42, 0x29, 0x30, 0xb1, 0x73, 0xd8,
+ 0x57, 0xb1, 0x3b, 0xc7, 0xbf, 0xf4, 0xd2, 0xee },
+ { 0x4e, 0xb9, 0x3b, 0x5c, 0xf3, 0xfa, 0x49, 0xec, 0x6f, 0x2d,
+ 0x7a, 0xda, 0x0f, 0x13, 0x87, 0x3a, 0x3e, 0x0e, 0x98, 0xe2,
+ 0xa9, 0x3b, 0x0d, 0xe4, 0x96, 0xf0, 0x52, 0x6d, 0x16, 0xab,
+ 0xed, 0xdd, 0x2c, 0x9c, 0x1c, 0xc1, 0x83, 0xf0, 0xf1, 0xc9,
+ 0xfa, 0x17, 0x63, 0x77, 0xef, 0x6b, 0x1e, 0x86, 0x48, 0xb7,
+ 0x93, 0x56, 0xcf, 0x6c, 0x80, 0xc7, 0x09, 0x13, 0x6a, 0x6e,
+ 0x28, 0x30, 0xec, 0xe2, 0x85, 0x06, 0xab, 0x37, 0x9c, 0x58,
+ 0x1e, 0x46, 0xdc, 0xcc, 0xbf, 0xb5, 0x7d, 0x65, 0x48, 0x68,
+ 0x31, 0x8d, 0xbc, 0x70, 0x34, 0xb0, 0xab, 0x0b, 0x5a, 0x03,
+ 0x2f, 0x8a, 0xa2, 0x9b, 0xe3, 0xdb, 0x4a, 0x6d, 0xd2, 0x26,
+ 0xbf, 0xfc, 0x14, 0x8e, 0x81, 0x49, 0x3d, 0x9f, 0xfa, 0xb5,
+ 0x22, 0x6f, 0xd4, 0x7b, 0x0b, 0xd8, 0x25, 0xaa, 0xda, 0xa0,
+ 0x91, 0xb7, 0xbb, 0x78, 0x1e, 0x8b, 0x76, 0x0d },
+ { 0x2b, 0x58, 0x2d, 0x93, 0x7c, 0x04, 0x3f, 0x68, 0xcd, 0xf5,
+ 0xc9, 0x0b, 0xc7, 0x00, 0x1c, 0xc8, 0x53, 0xe7, 0x81, 0xde,
+ 0x86, 0x80, 0x41, 0x72, 0x56, 0x05, 0xe2, 0x23, 0xe9, 0xc6,
+ 0xc4, 0xe0, 0xbf, 0x56, 0x54, 0x06, 0xa1, 0x9d, 0x48, 0xb6,
+ 0x82, 0xcf, 0xfd, 0xb3, 0xd9, 0x9f, 0x0c, 0x16, 0x18, 0x9a,
+ 0x5c, 0xc8, 0xbd, 0x8a, 0x68, 0x78, 0x12, 0xae, 0xef, 0xef,
+ 0xef, 0x3d, 0x51, 0x73, 0x93, 0x1c, 0x3f, 0x52, 0x75, 0x87,
+ 0x8a, 0x2a, 0xaf, 0xbb, 0xb6, 0x85, 0xfd, 0x33, 0x67, 0x6f,
+ 0x82, 0x22, 0x24, 0x19, 0xc1, 0x3c, 0xa2, 0xca, 0xbb, 0x9e,
+ 0x88, 0x97, 0x05, 0xba, 0x00, 0x68, 0x1d, 0x84, 0x9a, 0x57,
+ 0x55, 0x52, 0x79, 0xb7, 0x1b, 0x00, 0x14, 0xdf, 0x49, 0x1c,
+ 0x3f, 0x6f, 0xd1, 0x3d, 0x74, 0xf5, 0xc4, 0x02, 0x3f, 0x51,
+ 0xbd, 0x89, 0xf7, 0xe5, 0xe1, 0x1f, 0xae, 0x32 },
+ { 0x78, 0x61, 0x51, 0x09, 0x86, 0x2d, 0xb4, 0xc0, 0x4f, 0xa4,
+ 0x9c, 0xe3, 0xfa, 0x57, 0x4a, 0xfd, 0xc1, 0xd8, 0xeb, 0x48,
+ 0xeb, 0x7c, 0xee, 0x9a, 0x4b, 0xee, 0x10, 0xd7, 0xb3, 0xf2,
+ 0xf7, 0xaa, 0xfe, 0x8e, 0x33, 0xcd, 0xe9, 0x3a, 0xcf, 0xcd,
+ 0x91, 0x5c, 0x3d, 0x06, 0xf5, 0x08, 0x64, 0xa3, 0x71, 0xcb,
+ 0x93, 0x6b, 0x83, 0x1e, 0xdd, 0xfb, 0xa8, 0xe3, 0x92, 0x64,
+ 0x9e, 0x34, 0x8c, 0x09, 0xce, 0xed, 0x17, 0x2c, 0x2f, 0x11,
+ 0xc4, 0x1c, 0x85, 0xe2, 0x11, 0x03, 0xd9, 0xef, 0xf3, 0x2a,
+ 0x78, 0x75, 0x0d, 0xb4, 0xc9, 0x8d, 0xbd, 0xd5, 0xdc, 0xba,
+ 0xc9, 0xf3, 0xb5, 0x7f, 0xa2, 0x1c, 0x5d, 0x60, 0x38, 0x26,
+ 0x54, 0x77, 0x65, 0x06, 0xc0, 0x97, 0xb3, 0xd2, 0x07, 0xff,
+ 0xf6, 0x6f, 0xa7, 0x33, 0x80, 0xf5, 0xe2, 0xb6, 0x9e, 0xca,
+ 0xa1, 0x16, 0x5c, 0x82, 0x81, 0xab, 0xc2, 0xae },
+ { 0x54, 0x0b, 0x6b, 0xb7, 0x6b, 0xc9, 0xc0, 0x25, 0x9f, 0x9a,
+ 0x28, 0xab, 0x84, 0x16, 0x1c, 0x68, 0x6d, 0x51, 0xf9, 0x3c,
+ 0x3a, 0xa9, 0x56, 0xf9, 0xb4, 0xd8, 0x0e, 0xc0, 0xc3, 0xaf,
+ 0xa2, 0xcf, 0x64, 0x37, 0x36, 0x05, 0x54, 0x28, 0xde, 0xb5,
+ 0x0c, 0x8a, 0xdc, 0x05, 0x34, 0x37, 0x4c, 0x20, 0x18, 0xd4,
+ 0x04, 0xe4, 0x67, 0xb8, 0xe8, 0x7b, 0x57, 0xb7, 0x8b, 0x93,
+ 0x8e, 0xec, 0x6e, 0x1e, 0x9b, 0x0a, 0x43, 0xee, 0x28, 0x4d,
+ 0x3c, 0xcf, 0xbb, 0xe4, 0xed, 0x12, 0xf4, 0x27, 0xef, 0x5a,
+ 0x7a, 0x14, 0xcf, 0xfe, 0x82, 0xbd, 0x5f, 0xcd, 0x2a, 0x3a,
+ 0x43, 0x97, 0xd7, 0xcd, 0xbb, 0x24, 0x37, 0x9a, 0xe0, 0x94,
+ 0x51, 0xb4, 0xf1, 0xab, 0xc7, 0x6e, 0xe1, 0xe8, 0xf8, 0xc3,
+ 0xa4, 0x54, 0x63, 0x1a, 0xa1, 0x44, 0xfd, 0x0f, 0x0d, 0xa5,
+ 0x3f, 0xe3, 0xf4, 0x80, 0x7a, 0xe7, 0x2c, 0x21 },
+ { 0x89, 0x7c, 0xab, 0x14, 0x92, 0xe0, 0x38, 0x8c, 0x2c, 0xa2,
+ 0x58, 0x67, 0x52, 0xdd, 0x50, 0xf6, 0xe1, 0xc2, 0x87, 0x76,
+ 0x5e, 0x20, 0xe8, 0x18, 0x3d, 0xb7, 0xd1, 0xa3, 0x44, 0x61,
+ 0xcd, 0x29, 0xe0, 0xb5, 0x05, 0xa1, 0x75, 0x02, 0x05, 0x38,
+ 0xf6, 0x9d, 0x98, 0xf0, 0x7c, 0xad, 0xf0, 0xe9, 0xdc, 0xe7,
+ 0xda, 0xbe, 0x0c, 0x92, 0x4d, 0x60, 0x2a, 0x97, 0x3d, 0x97,
+ 0xaa, 0xbf, 0x65, 0x85, 0x43, 0xaf, 0xbc, 0x78, 0xea, 0x36,
+ 0x2f, 0x45, 0x43, 0x6d, 0xb2, 0x93, 0x1d, 0x62, 0x98, 0xeb,
+ 0x2e, 0x4a, 0x83, 0x7e, 0xb9, 0xbc, 0x53, 0xde, 0x6a, 0x21,
+ 0xe9, 0xad, 0x58, 0x77, 0x57, 0x0f, 0x1f, 0xb0, 0x7a, 0x49,
+ 0xac, 0xdc, 0x78, 0x9a, 0xea, 0xfa, 0xe1, 0x45, 0xbb, 0xa8,
+ 0xcd, 0x81, 0x4e, 0xf5, 0x66, 0x12, 0xd8, 0x6e, 0x05, 0xd0,
+ 0x04, 0xe1, 0x73, 0x4c, 0x32, 0x1d, 0x31, 0x5d },
+ { 0x64, 0xb0, 0x07, 0x63, 0x47, 0x6b, 0x0e, 0xc5, 0xdc, 0x62,
+ 0xc4, 0xa4, 0xff, 0xf6, 0x73, 0xaa, 0x2f, 0xf4, 0x7d, 0xac,
+ 0x30, 0xeb, 0x93, 0xa5, 0x2c, 0x82, 0x2e, 0x67, 0x20, 0xa5,
+ 0x18, 0x2d, 0xab, 0x90, 0x6b, 0xa3, 0xbf, 0x6c, 0xd9, 0x49,
+ 0x82, 0xf6, 0x29, 0xaa, 0xa6, 0xc2, 0x4f, 0xa6, 0x56, 0x4f,
+ 0x2a, 0x4d, 0xcf, 0x0a, 0xc9, 0x3e, 0x44, 0xf8, 0xf7, 0xfb,
+ 0x14, 0xfa, 0x88, 0xd2, 0xd8, 0x83, 0x62, 0x8b, 0x6c, 0x91,
+ 0x2f, 0xe0, 0x70, 0xd2, 0xed, 0x84, 0x0d, 0x1a, 0x83, 0x1e,
+ 0x74, 0x98, 0x4b, 0x11, 0xf3, 0x83, 0x37, 0x1c, 0x44, 0x92,
+ 0x81, 0x05, 0xb9, 0x74, 0x11, 0xa0, 0x86, 0xad, 0x0d, 0x3a,
+ 0x7a, 0xc8, 0x96, 0x74, 0x06, 0x87, 0xbf, 0x2c, 0x40, 0x58,
+ 0x14, 0x15, 0xc1, 0x1d, 0x36, 0x4c, 0xa4, 0x38, 0x20, 0x0a,
+ 0x59, 0xed, 0x38, 0x13, 0x0d, 0x8b, 0xab, 0x8a },
+ { 0x7d, 0xd2, 0x2e, 0xa6, 0x66, 0x18, 0xed, 0x8c, 0x29, 0x1f,
+ 0xb8, 0x2c, 0x09, 0xe5, 0x0e, 0x84, 0x25, 0x55, 0x94, 0x24,
+ 0x19, 0xd6, 0x8e, 0x36, 0xe3, 0x92, 0x51, 0x53, 0x57, 0x6c,
+ 0xa9, 0x64, 0x0b, 0x52, 0xc3, 0x9f, 0xb0, 0x70, 0xa2, 0x93,
+ 0x80, 0x17, 0x8b, 0x12, 0xc2, 0x37, 0x00, 0x2a, 0xfb, 0xc7,
+ 0x6f, 0x56, 0xe1, 0x21, 0x7a, 0x95, 0x42, 0xda, 0xf0, 0xbb,
+ 0x9e, 0xf5, 0x55, 0x1c, 0x21, 0x7c, 0xab, 0x32, 0xc3, 0x9b,
+ 0x5a, 0xcf, 0x3f, 0x8f, 0xc0, 0x9d, 0xdc, 0x08, 0x4e, 0x01,
+ 0xd8, 0x78, 0x49, 0x35, 0x01, 0xec, 0x5c, 0xf1, 0xcc, 0xfd,
+ 0x3b, 0x33, 0xce, 0x26, 0xca, 0xd0, 0x7c, 0xe7, 0xf4, 0xc4,
+ 0x07, 0x38, 0xee, 0xd4, 0xc7, 0xf1, 0x3e, 0x29, 0x6c, 0x25,
+ 0x36, 0x93, 0xb1, 0xdb, 0x7f, 0x73, 0xb7, 0xef, 0x99, 0x52,
+ 0x1e, 0x3f, 0x53, 0x3e, 0xb3, 0xc9, 0xa4, 0x04 },
+ { 0x31, 0x37, 0x7c, 0x66, 0x5f, 0x18, 0xfc, 0xc8, 0x95, 0x59,
+ 0xc8, 0x8a, 0xb1, 0x3b, 0x74, 0x89, 0x5c, 0x8f, 0x98, 0xfc,
+ 0x51, 0xca, 0xdf, 0x0f, 0x68, 0x5f, 0xf9, 0x4b, 0xbd, 0x3b,
+ 0x9d, 0x82, 0x95, 0xf9, 0x49, 0x30, 0xda, 0xc6, 0xf7, 0x90,
+ 0x60, 0xaf, 0xd4, 0x47, 0xb6, 0xf6, 0xa9, 0x16, 0x41, 0x64,
+ 0x03, 0xc1, 0x14, 0x14, 0xa4, 0x85, 0x67, 0xa9, 0xf6, 0x33,
+ 0x20, 0x1a, 0x42, 0x37, 0x6b, 0x0d, 0x3d, 0xdd, 0x83, 0x24,
+ 0x7b, 0x72, 0x8c, 0xf4, 0xeb, 0x32, 0x82, 0xe5, 0x74, 0x2b,
+ 0x39, 0xa1, 0x48, 0x92, 0x96, 0x95, 0x7f, 0x34, 0x2c, 0x75,
+ 0xd4, 0xb9, 0x30, 0x63, 0x57, 0x18, 0x95, 0x6d, 0x7f, 0x26,
+ 0xe5, 0x12, 0x77, 0xfc, 0x1e, 0x6e, 0xe5, 0x37, 0x9f, 0x5a,
+ 0x84, 0x5a, 0xde, 0x0c, 0xc7, 0x04, 0x55, 0x62, 0xfb, 0x25,
+ 0x7f, 0xfe, 0x84, 0x4b, 0x49, 0xcb, 0xb3, 0xbf },
+ { 0x3d, 0xac, 0xc5, 0x0c, 0xa1, 0x1e, 0x52, 0x71, 0x3a, 0x5f,
+ 0xd6, 0x95, 0x58, 0x7e, 0xda, 0xbd, 0xef, 0x45, 0x42, 0x3c,
+ 0x64, 0x8a, 0x01, 0x79, 0xe2, 0x89, 0xd0, 0x24, 0x0c, 0x8f,
+ 0x45, 0x24, 0xb3, 0x5a, 0x98, 0x24, 0x00, 0xd5, 0xe4, 0x67,
+ 0xd8, 0xf9, 0x93, 0xb6, 0x05, 0x62, 0x4d, 0xd2, 0xfc, 0xf3,
+ 0x64, 0xfa, 0xa9, 0x50, 0x70, 0xe0, 0x44, 0x09, 0x76, 0x63,
+ 0x03, 0xd3, 0xe6, 0x0a, 0xe5, 0x2e, 0xfb, 0x53, 0x69, 0xe9,
+ 0x0a, 0x6f, 0x43, 0x98, 0x80, 0xcf, 0x25, 0x96, 0xda, 0xd2,
+ 0x75, 0x2e, 0xd1, 0x59, 0x71, 0xbf, 0xe6, 0x07, 0x9d, 0x95,
+ 0xcd, 0x4f, 0xb0, 0x9a, 0x19, 0xb5, 0x0c, 0x2d, 0xd4, 0x8a,
+ 0xf7, 0xb4, 0xb3, 0x75, 0x7e, 0x93, 0xe8, 0x5d, 0x75, 0x76,
+ 0xcb, 0x63, 0x2d, 0xcc, 0xca, 0x9f, 0x01, 0xcc, 0x36, 0xf8,
+ 0x35, 0xc5, 0xde, 0x09, 0x7d, 0xcf, 0xb3, 0x5f },
+ { 0x86, 0x69, 0x49, 0xe1, 0x69, 0x47, 0x44, 0xf7, 0x46, 0x9b,
+ 0x75, 0x61, 0x23, 0x24, 0x8a, 0x31, 0xbe, 0xd3, 0xf2, 0xc3,
+ 0xe0, 0x69, 0xdf, 0x05, 0x5d, 0xd2, 0xdf, 0x7a, 0x60, 0xdf,
+ 0x19, 0x4d, 0xcd, 0x1e, 0xfd, 0xb4, 0xf3, 0xe9, 0xdf, 0x64,
+ 0x6f, 0xd5, 0x76, 0x87, 0xf9, 0xdd, 0x9f, 0x0a, 0x7a, 0xb2,
+ 0x44, 0x04, 0xb1, 0x7b, 0x28, 0x42, 0xe5, 0x1a, 0x0d, 0x53,
+ 0x88, 0x07, 0xf3, 0xa0, 0x0a, 0x9b, 0xa3, 0x85, 0xb9, 0xbf,
+ 0xd2, 0xfb, 0xf3, 0xfb, 0x62, 0x10, 0xae, 0xc2, 0x3e, 0xaf,
+ 0xf7, 0xb7, 0xb9, 0xba, 0xdf, 0x1c, 0xdb, 0x49, 0xf3, 0x5e,
+ 0x45, 0x18, 0xaa, 0x28, 0x6f, 0xd0, 0xb6, 0xc6, 0x4d, 0x28,
+ 0xd8, 0x48, 0x1e, 0x45, 0x80, 0x7f, 0x5c, 0xe9, 0xbe, 0x78,
+ 0x2e, 0x8a, 0xa4, 0x6d, 0xcb, 0xe1, 0x70, 0x53, 0xc5, 0x27,
+ 0xcb, 0x3e, 0x4f, 0x94, 0x64, 0x99, 0xae, 0x4c },
+ { 0x57, 0x43, 0x52, 0xb8, 0x8b, 0x1f, 0xa5, 0x98, 0xdc, 0x38,
+ 0x84, 0xff, 0x5b, 0x08, 0x31, 0x77, 0xc2, 0xd3, 0x83, 0x73,
+ 0x94, 0xf7, 0xec, 0x4e, 0x37, 0xa5, 0x05, 0x69, 0xc2, 0x95,
+ 0xdc, 0x46, 0xfa, 0x84, 0x4e, 0xb0, 0x7b, 0x96, 0xd4, 0x80,
+ 0x0d, 0x2b, 0x84, 0x1b, 0x33, 0x29, 0xdb, 0x82, 0x85, 0x2d,
+ 0x44, 0x35, 0x4e, 0x2d, 0x5d, 0xd0, 0xd7, 0x9d, 0xb1, 0xbb,
+ 0xd7, 0x4c, 0x70, 0x91, 0x3b, 0x66, 0x4b, 0x1e, 0x7d, 0x08,
+ 0x77, 0xb5, 0x50, 0x01, 0x39, 0x4e, 0x99, 0x0c, 0x03, 0xa0,
+ 0x38, 0x59, 0x8e, 0xa1, 0x06, 0x6c, 0xb4, 0xd7, 0x93, 0xaf,
+ 0x1f, 0xbd, 0xd3, 0xb2, 0x18, 0xab, 0xc9, 0x58, 0x1c, 0x3e,
+ 0x84, 0x8e, 0x3d, 0x58, 0x0c, 0x92, 0xe9, 0x21, 0xb2, 0x3c,
+ 0xf2, 0x90, 0x2c, 0xd6, 0xf3, 0x33, 0xf5, 0x4a, 0x6f, 0xbf,
+ 0x3a, 0x9a, 0x0d, 0xa5, 0x3f, 0x4a, 0xb0, 0x7a },
+ { 0x3e, 0x43, 0x1a, 0xf2, 0x06, 0xae, 0x3c, 0x4f, 0x24, 0x18,
+ 0xc6, 0x24, 0xd3, 0xb6, 0xa3, 0xa1, 0x38, 0x84, 0xd5, 0xd8,
+ 0xf8, 0x53, 0xa9, 0x4e, 0x5f, 0xcb, 0xcc, 0x09, 0x69, 0x96,
+ 0x01, 0x1a, 0x44, 0x45, 0x21, 0xa1, 0x09, 0x9f, 0x68, 0x73,
+ 0x3f, 0x20, 0x43, 0x40, 0xd2, 0x94, 0x64, 0x93, 0x25, 0x3a,
+ 0x3a, 0x69, 0xf0, 0xd6, 0x78, 0x2b, 0xa9, 0x63, 0x35, 0xbc,
+ 0x09, 0x1c, 0x19, 0xeb, 0x4e, 0x76, 0x48, 0xc7, 0x61, 0xc2,
+ 0x20, 0x1d, 0x99, 0x6c, 0xca, 0xf0, 0xde, 0x20, 0x28, 0xd8,
+ 0x2e, 0xc2, 0x7e, 0x49, 0x28, 0x59, 0x85, 0xdf, 0x8a, 0x84,
+ 0xec, 0x00, 0xba, 0xa7, 0x01, 0x98, 0xdd, 0x9d, 0xa8, 0x60,
+ 0x78, 0x27, 0x0d, 0x56, 0x7c, 0x44, 0xab, 0x59, 0x7b, 0xe6,
+ 0x5f, 0xd0, 0x3c, 0x19, 0xfd, 0x26, 0x0b, 0x48, 0x7e, 0xaf,
+ 0xed, 0x21, 0x93, 0xf7, 0x0d, 0x5d, 0x7c, 0xe9 },
+ { 0x6d, 0xad, 0x3f, 0x15, 0xe2, 0x66, 0x4d, 0x35, 0x1c, 0x3d,
+ 0x7d, 0x82, 0xa2, 0x03, 0xce, 0xf1, 0x8a, 0x0f, 0xbb, 0xd1,
+ 0x86, 0xbb, 0xfa, 0x41, 0xf2, 0x69, 0x31, 0xba, 0xad, 0x89,
+ 0x6c, 0x2a, 0xcd, 0x57, 0x76, 0x66, 0x53, 0xbb, 0xb3, 0x43,
+ 0x4f, 0x1c, 0x96, 0x86, 0x11, 0xe9, 0x35, 0xc5, 0x7f, 0xc2,
+ 0xa3, 0xed, 0x85, 0x1e, 0xe4, 0x1e, 0xfd, 0x1b, 0xfe, 0x44,
+ 0x1a, 0x94, 0x2f, 0x7d, 0x33, 0x6a, 0x4f, 0xda, 0xae, 0xfd,
+ 0xb6, 0x46, 0xd0, 0x90, 0xa6, 0xa3, 0xaa, 0x45, 0x6d, 0x6f,
+ 0xfe, 0xb2, 0xaf, 0xa6, 0x36, 0xf0, 0xb7, 0x55, 0x43, 0xae,
+ 0x07, 0x41, 0xd9, 0x2f, 0x29, 0x00, 0xa8, 0x6d, 0x15, 0x98,
+ 0x50, 0x93, 0xa6, 0xd3, 0xbf, 0x3a, 0xf4, 0xd0, 0x54, 0x41,
+ 0x07, 0x68, 0x36, 0x50, 0x1a, 0xae, 0xd0, 0xc0, 0x33, 0xc3,
+ 0xf9, 0x67, 0xd9, 0x39, 0x83, 0xd3, 0x81, 0xf1 },
+ { 0x24, 0x38, 0xe9, 0xd4, 0x5f, 0x51, 0x7a, 0x3f, 0xc8, 0x7a,
+ 0x53, 0x90, 0x27, 0xd2, 0xd5, 0x5f, 0xfc, 0x3e, 0xe7, 0xc6,
+ 0x0b, 0xff, 0x83, 0x7c, 0x56, 0x59, 0x0b, 0xa4, 0x93, 0x83,
+ 0xd2, 0xd3, 0x08, 0xe5, 0x84, 0x48, 0x67, 0x23, 0x75, 0xc5,
+ 0x11, 0x09, 0xa6, 0x13, 0xdf, 0x3a, 0x8d, 0xc3, 0x51, 0x7f,
+ 0x2f, 0x1d, 0xbe, 0xbd, 0x01, 0x29, 0xb0, 0x69, 0x59, 0x9d,
+ 0xf8, 0x95, 0x8c, 0x6f, 0x7a, 0x41, 0x40, 0x21, 0x71, 0x98,
+ 0xb2, 0x1b, 0x97, 0x4a, 0x9f, 0x03, 0x8c, 0x0a, 0xcb, 0xa7,
+ 0x06, 0x1b, 0xc9, 0x26, 0xc3, 0xd9, 0x6a, 0x19, 0x15, 0x09,
+ 0x0f, 0x55, 0xd9, 0x90, 0x3c, 0x43, 0x5e, 0x76, 0x90, 0x4a,
+ 0x33, 0xc5, 0x8e, 0xb6, 0x2c, 0xc2, 0x78, 0xc6, 0xf1, 0x33,
+ 0x21, 0xd5, 0x62, 0x19, 0xc5, 0xb6, 0xe7, 0xdf, 0xb1, 0x28,
+ 0xd1, 0x94, 0x0b, 0x7d, 0x12, 0xec, 0x35, 0xa1 },
+ { 0x13, 0xf3, 0x90, 0x11, 0xaf, 0xe3, 0x0e, 0x01, 0x00, 0xa8,
+ 0xb7, 0xb2, 0x96, 0x20, 0x0e, 0x67, 0x9d, 0x2a, 0x97, 0xcd,
+ 0xff, 0x79, 0x5b, 0xb3, 0xf4, 0xad, 0xa5, 0x11, 0xbd, 0x41,
+ 0x6b, 0x67, 0xdd, 0xb4, 0x7c, 0x73, 0x68, 0xf1, 0xf7, 0xf2,
+ 0x8b, 0x33, 0xef, 0x46, 0x2a, 0x51, 0x34, 0x90, 0xf1, 0xb4,
+ 0x63, 0x3c, 0xd7, 0x70, 0x1f, 0x5b, 0x20, 0x5b, 0x4c, 0x89,
+ 0x1b, 0xe2, 0x81, 0xcb, 0x71, 0x50, 0xe0, 0x4b, 0x6b, 0xbc,
+ 0x4f, 0xb1, 0xf7, 0x37, 0xc3, 0xc2, 0xf1, 0xda, 0x60, 0x10,
+ 0x6f, 0x14, 0x42, 0x9c, 0xd0, 0xb3, 0xe2, 0x31, 0xbd, 0x0d,
+ 0xac, 0x54, 0xe6, 0x3f, 0x24, 0x90, 0x61, 0xc6, 0x1d, 0x94,
+ 0x12, 0xe5, 0x1e, 0xb5, 0xae, 0xf1, 0xcd, 0xc9, 0x97, 0xb6,
+ 0x5d, 0xdf, 0xe5, 0x5f, 0x1a, 0x32, 0xf3, 0xc9, 0xbe, 0xd5,
+ 0xc4, 0xa4, 0x53, 0x08, 0x88, 0x15, 0xaf, 0x3c },
+ { 0x45, 0x8d, 0x4b, 0x6b, 0x68, 0x07, 0x03, 0xb6, 0x17, 0xa7,
+ 0xce, 0x24, 0xcb, 0xda, 0x1b, 0x0b, 0x29, 0x84, 0x66, 0xd4,
+ 0x72, 0x2b, 0x7b, 0xc9, 0xbc, 0x07, 0x5b, 0x73, 0xd8, 0xc4,
+ 0xba, 0x8b, 0x33, 0xdd, 0x77, 0xa0, 0x1c, 0xf2, 0xb8, 0x66,
+ 0x24, 0x97, 0xe0, 0xbf, 0xa4, 0xd8, 0xd0, 0x18, 0xfe, 0x31,
+ 0x1a, 0xd0, 0x1b, 0xbd, 0xa0, 0x05, 0xce, 0xea, 0x99, 0xd5,
+ 0x56, 0x41, 0x51, 0x10, 0x29, 0x3b, 0xb5, 0xe7, 0x53, 0x5c,
+ 0x5d, 0x0b, 0x2a, 0x83, 0x8c, 0xa8, 0x26, 0x3b, 0x60, 0x62,
+ 0x3f, 0x90, 0xd7, 0x10, 0x68, 0xc0, 0xe5, 0x84, 0xcb, 0xb8,
+ 0x30, 0x24, 0x99, 0x80, 0x45, 0xdf, 0xde, 0x8d, 0x80, 0x45,
+ 0x26, 0x8b, 0xca, 0x77, 0xf8, 0x79, 0x30, 0x68, 0x1c, 0x9a,
+ 0x51, 0x5a, 0x50, 0x61, 0x10, 0xf3, 0x4a, 0x29, 0xff, 0x46,
+ 0x3d, 0xd2, 0x96, 0xef, 0x7b, 0xd0, 0xc8, 0x27 },
+ { 0x5f, 0x13, 0xf5, 0xfa, 0xb6, 0xfb, 0xbf, 0x91, 0x62, 0x8e,
+ 0x3b, 0x06, 0x56, 0x68, 0xf9, 0x5c, 0x00, 0xae, 0x04, 0x57,
+ 0x62, 0x4d, 0xb0, 0x1a, 0x32, 0x59, 0xef, 0x18, 0x2f, 0x72,
+ 0x55, 0x6b, 0x68, 0xef, 0x0b, 0x70, 0x8f, 0x27, 0xd4, 0x9f,
+ 0x21, 0xae, 0x03, 0x19, 0x97, 0x84, 0x70, 0x64, 0xfe, 0x5b,
+ 0x5c, 0xb5, 0x85, 0xc9, 0xeb, 0x8a, 0x3e, 0xfc, 0x2e, 0x9b,
+ 0x1b, 0x48, 0x20, 0xc3, 0xea, 0xe9, 0x5e, 0xa5, 0x99, 0x23,
+ 0x02, 0x20, 0xe1, 0x0a, 0x14, 0x49, 0xa1, 0xb3, 0x64, 0x10,
+ 0x46, 0xb9, 0xb0, 0x00, 0x73, 0x04, 0x02, 0xbd, 0x18, 0x12,
+ 0xe8, 0x19, 0x36, 0x94, 0xd0, 0x0d, 0x7a, 0x4a, 0xdc, 0x3c,
+ 0x2f, 0x65, 0x49, 0xa8, 0x69, 0x8b, 0x58, 0x58, 0xf9, 0x94,
+ 0xf7, 0x00, 0x05, 0xa5, 0x69, 0x6e, 0x4d, 0x32, 0x0a, 0x0d,
+ 0x8a, 0x26, 0xa2, 0x0e, 0x4d, 0x54, 0xd8, 0xb2 },
+ { 0x21, 0x96, 0x49, 0x5d, 0xa3, 0x7b, 0xa4, 0xa2, 0x11, 0x62,
+ 0x5a, 0x44, 0x05, 0xf8, 0x02, 0xf6, 0x35, 0x0d, 0xc5, 0x65,
+ 0x6f, 0x5a, 0x17, 0x4d, 0x7c, 0x0a, 0x3c, 0x53, 0x17, 0x71,
+ 0x3a, 0x1a, 0x37, 0xc9, 0xe3, 0xa2, 0xe8, 0x03, 0xe6, 0x9c,
+ 0x90, 0xac, 0xb2, 0x90, 0x25, 0xce, 0xc9, 0x9c, 0x73, 0x71,
+ 0x3e, 0x66, 0x55, 0xbf, 0x1c, 0xa7, 0x0e, 0xed, 0x92, 0xdf,
+ 0x6b, 0x9c, 0x48, 0x2d, 0xfd, 0xf0, 0xec, 0xe7, 0xc3, 0x59,
+ 0x89, 0xca, 0x1f, 0x0f, 0xdf, 0x17, 0x7d, 0x11, 0x67, 0x4e,
+ 0xf7, 0x41, 0xc8, 0xf2, 0x29, 0x0d, 0xf0, 0x5c, 0xc4, 0xd3,
+ 0x31, 0x7b, 0x68, 0x21, 0x7f, 0xfd, 0xde, 0xfa, 0x6a, 0xbc,
+ 0x9a, 0x66, 0xe3, 0xab, 0xea, 0x66, 0xbf, 0x88, 0xea, 0x8b,
+ 0x36, 0x77, 0xae, 0xa1, 0xbd, 0xe9, 0x6f, 0x88, 0x3e, 0xc8,
+ 0x7c, 0x6e, 0xd9, 0xae, 0x3a, 0x9b, 0x0d, 0xc6 },
+ { 0x93, 0xad, 0x0e, 0xb0, 0x04, 0x47, 0x5f, 0x08, 0x29, 0x71,
+ 0xce, 0xa7, 0x3d, 0x56, 0xfa, 0x62, 0x5a, 0xa0, 0xc4, 0x7d,
+ 0x6c, 0xe5, 0x48, 0xa0, 0x04, 0xa1, 0x79, 0x40, 0xd2, 0x18,
+ 0x97, 0xc1, 0x33, 0xef, 0x7b, 0xc3, 0x42, 0x7f, 0x34, 0x35,
+ 0x2c, 0x3c, 0x8c, 0xbd, 0x14, 0x41, 0x54, 0xb0, 0x9f, 0xf1,
+ 0x09, 0x52, 0x9a, 0xaa, 0xa4, 0x04, 0xc4, 0x8e, 0xfc, 0x6b,
+ 0x95, 0xb1, 0x97, 0xf9, 0xf3, 0x69, 0x31, 0x29, 0x8e, 0x8f,
+ 0x7d, 0xb5, 0x97, 0x09, 0xbc, 0x28, 0x51, 0x6e, 0xc8, 0xec,
+ 0x84, 0xad, 0xb1, 0xa2, 0xd7, 0x38, 0xf1, 0xff, 0x3c, 0x2b,
+ 0x79, 0x86, 0xcb, 0x6e, 0xc2, 0x50, 0xbe, 0xef, 0xce, 0x58,
+ 0x0a, 0xe2, 0x2b, 0xc5, 0xc6, 0xa0, 0xce, 0xab, 0xdf, 0xe2,
+ 0x66, 0x9e, 0xab, 0x9e, 0x91, 0xd7, 0x65, 0xd1, 0x4c, 0xf4,
+ 0x00, 0xcb, 0x2f, 0xd3, 0x13, 0x14, 0x26, 0x80 },
+ { 0x73, 0xf8, 0xc3, 0xf0, 0xea, 0x41, 0xc0, 0x34, 0x44, 0x08,
+ 0xdd, 0x42, 0x58, 0x44, 0xd1, 0xf9, 0x2b, 0x95, 0x22, 0x09,
+ 0x57, 0x6e, 0x58, 0x8d, 0xc5, 0xfc, 0x88, 0xd5, 0x44, 0x17,
+ 0xea, 0xde, 0x05, 0x86, 0xf7, 0x2f, 0xbc, 0xcd, 0xe4, 0x51,
+ 0xe5, 0x67, 0x4c, 0x4b, 0xf8, 0x23, 0xd7, 0x97, 0xef, 0x8a,
+ 0x94, 0x48, 0xc9, 0x01, 0x6c, 0x8c, 0x1d, 0x56, 0x46, 0xb8,
+ 0x14, 0x3f, 0xe0, 0x79, 0xc0, 0x4e, 0xd0, 0xb7, 0x26, 0xe6,
+ 0x62, 0xf7, 0x25, 0x4c, 0x05, 0xc3, 0xe0, 0x2f, 0xcc, 0xcf,
+ 0x18, 0xf6, 0xf0, 0x9c, 0x13, 0x02, 0xe3, 0x23, 0x3c, 0x38,
+ 0xd3, 0xfb, 0x68, 0x7a, 0x5b, 0x3d, 0x63, 0xa9, 0xb8, 0xd5,
+ 0xd3, 0x39, 0x22, 0xde, 0x62, 0x74, 0xe3, 0x86, 0x3b, 0x6b,
+ 0x50, 0xf2, 0x61, 0xe4, 0x77, 0xf7, 0x65, 0x15, 0xe8, 0xdd,
+ 0x7a, 0x0b, 0x69, 0x67, 0x98, 0x8a, 0x99, 0x63 },
+ { 0x01, 0x08, 0xae, 0x39, 0xad, 0xbe, 0xdd, 0x75, 0xdf, 0xed,
+ 0x25, 0xd9, 0x7c, 0xaa, 0x51, 0xb8, 0x7c, 0xf9, 0xd4, 0x07,
+ 0x21, 0x34, 0x1a, 0x8a, 0x0f, 0x26, 0x87, 0x45, 0xfc, 0xa3,
+ 0x25, 0xe4, 0xa2, 0xe0, 0x58, 0xfc, 0xb1, 0x5a, 0xe2, 0x06,
+ 0xa1, 0x4e, 0x05, 0x52, 0x2d, 0x16, 0xe3, 0x61, 0x96, 0x3d,
+ 0xee, 0xa6, 0x28, 0xb7, 0x91, 0xcc, 0xef, 0xff, 0x6d, 0xae,
+ 0x33, 0x21, 0xed, 0xcd, 0x74, 0x9e, 0x0d, 0x98, 0xea, 0x36,
+ 0xa0, 0x15, 0x62, 0x6e, 0xec, 0xf1, 0x29, 0x3a, 0xa8, 0xcf,
+ 0xaa, 0x58, 0x44, 0x28, 0x51, 0x9f, 0x7b, 0xf3, 0x78, 0x04,
+ 0xc9, 0xad, 0x85, 0x7c, 0xae, 0xa6, 0x1d, 0x39, 0x09, 0x44,
+ 0xcb, 0x20, 0x88, 0x8e, 0x0d, 0xb5, 0xbe, 0x17, 0x6e, 0x8f,
+ 0x15, 0xa0, 0x3b, 0x14, 0x27, 0xf3, 0x3a, 0xc7, 0x18, 0x36,
+ 0x89, 0x53, 0x4f, 0xc8, 0x5d, 0xf7, 0x63, 0xdd },
+ { 0x80, 0x7c, 0x06, 0xd8, 0xeb, 0x13, 0xc1, 0xdf, 0x34, 0x8b,
+ 0xb4, 0x2f, 0xa0, 0xc4, 0x52, 0x33, 0x88, 0x48, 0x08, 0x9b,
+ 0xac, 0x85, 0xa4, 0xe1, 0xdf, 0xfc, 0x46, 0xab, 0xd5, 0x09,
+ 0x7e, 0x1f, 0x0c, 0x9a, 0xad, 0x75, 0x44, 0x5d, 0xad, 0x00,
+ 0x88, 0x89, 0x1e, 0x36, 0xfb, 0x3a, 0x9b, 0x17, 0xfb, 0xbe,
+ 0x4b, 0xe8, 0x1e, 0xe0, 0xa5, 0x99, 0xc3, 0xf6, 0x5b, 0x99,
+ 0x46, 0xc5, 0xda, 0xfc, 0xdd, 0xc8, 0x38, 0x03, 0x9d, 0x59,
+ 0x51, 0x1a, 0x16, 0xaf, 0x05, 0x99, 0x0c, 0xc6, 0x9c, 0x89,
+ 0xfc, 0x8b, 0xef, 0xe7, 0x54, 0xe3, 0x09, 0x0b, 0xde, 0x10,
+ 0xb0, 0x73, 0xe9, 0xbb, 0x00, 0x4d, 0x24, 0xdb, 0x7d, 0xae,
+ 0x8d, 0x0b, 0x91, 0xc8, 0x77, 0x3a, 0x53, 0xe6, 0xe2, 0x61,
+ 0xd8, 0xa6, 0xaa, 0x05, 0xb1, 0x1e, 0xab, 0x0c, 0x73, 0x25,
+ 0x54, 0xd1, 0x78, 0xf3, 0xa9, 0xe8, 0x8f, 0x63 },
+ { 0x16, 0x42, 0x4c, 0x6c, 0x99, 0x60, 0x7a, 0x61, 0xb2, 0xfd,
+ 0xfa, 0x36, 0xb5, 0x53, 0x99, 0xfc, 0x26, 0x92, 0xc6, 0x26,
+ 0x17, 0x58, 0x3b, 0x53, 0xaa, 0xc4, 0xff, 0xcf, 0xc3, 0x9b,
+ 0x06, 0x34, 0x93, 0xf1, 0x80, 0xf7, 0xfa, 0x2f, 0x35, 0x8b,
+ 0x5d, 0xf7, 0x6b, 0x3a, 0xef, 0x0f, 0x27, 0x5a, 0x08, 0xff,
+ 0x7d, 0x15, 0x99, 0x82, 0x11, 0xa4, 0x89, 0xb5, 0x68, 0x81,
+ 0xf7, 0x21, 0x09, 0xbd, 0xce, 0x15, 0x25, 0xc9, 0xed, 0x39,
+ 0x9c, 0x0e, 0x97, 0x4d, 0xb3, 0xde, 0xda, 0x86, 0x1d, 0x3b,
+ 0x53, 0xa9, 0xa9, 0x42, 0x99, 0x8c, 0x95, 0xfb, 0xe5, 0x93,
+ 0x43, 0xe4, 0x60, 0xad, 0x1a, 0xf2, 0x7b, 0xdb, 0x20, 0x1a,
+ 0x8b, 0x70, 0x55, 0x7c, 0x24, 0x48, 0x4c, 0x92, 0xa0, 0x2f,
+ 0x8f, 0xdb, 0xba, 0x9d, 0x54, 0x83, 0x8b, 0xb7, 0xb7, 0xaf,
+ 0x00, 0xa9, 0x69, 0xec, 0x98, 0xee, 0x0e, 0xf6 },
+ { 0x55, 0x44, 0xe6, 0x02, 0xa4, 0xf4, 0x47, 0x8a, 0xdd, 0xda,
+ 0xf4, 0xb9, 0xfb, 0x58, 0x31, 0xb1, 0x3d, 0xfe, 0x6b, 0xc1,
+ 0x72, 0x53, 0xa5, 0x1b, 0xa3, 0xc9, 0xad, 0xff, 0xac, 0xcc,
+ 0xb8, 0x5c, 0x47, 0x4a, 0x3e, 0x14, 0xf0, 0x3d, 0xed, 0x28,
+ 0x3d, 0x16, 0xfc, 0x45, 0x45, 0xb0, 0xe9, 0xeb, 0xa9, 0xe6,
+ 0x55, 0xe4, 0x2e, 0x7f, 0x34, 0x04, 0x44, 0xff, 0x67, 0xb9,
+ 0xed, 0x64, 0xd1, 0x2c, 0xd4, 0x39, 0x61, 0x41, 0x4b, 0x8e,
+ 0xfa, 0x0c, 0x88, 0xae, 0x40, 0x98, 0xbc, 0xc7, 0x72, 0x72,
+ 0xbc, 0xec, 0xd2, 0x58, 0xca, 0xf2, 0xd1, 0x22, 0x98, 0x38,
+ 0x45, 0x50, 0x9b, 0xe9, 0x96, 0x74, 0x30, 0xb7, 0xab, 0x25,
+ 0xa9, 0xdf, 0x69, 0x1a, 0x32, 0xc8, 0x2e, 0x99, 0xef, 0xe8,
+ 0xb0, 0x89, 0x25, 0x44, 0xc1, 0xc2, 0xfe, 0x3a, 0xf4, 0x18,
+ 0x5d, 0xd6, 0x5c, 0x55, 0xdd, 0x27, 0x44, 0xa9 },
+ { 0x57, 0x35, 0x99, 0x5c, 0xe2, 0x41, 0xd2, 0x61, 0xdd, 0x7d,
+ 0x3e, 0xdd, 0x1e, 0xd6, 0x0f, 0x42, 0xc1, 0xa4, 0xcd, 0xce,
+ 0x2d, 0xec, 0x53, 0xcf, 0x80, 0xb7, 0xec, 0xdc, 0x22, 0x99,
+ 0x4b, 0x43, 0x72, 0x0b, 0x59, 0xde, 0x19, 0xb1, 0xb5, 0x40,
+ 0xd0, 0xf7, 0x0e, 0x6e, 0xb2, 0x79, 0x46, 0x81, 0x76, 0xc8,
+ 0x8b, 0xd2, 0x09, 0xd0, 0x9a, 0xf1, 0x83, 0x10, 0x74, 0x46,
+ 0xcb, 0x42, 0x03, 0x3c, 0x20, 0x53, 0xc5, 0xe0, 0x1f, 0x6c,
+ 0x7d, 0x29, 0x83, 0x49, 0xdd, 0x73, 0xc2, 0x90, 0xd9, 0xd8,
+ 0x16, 0x3d, 0x05, 0x00, 0xed, 0x94, 0x58, 0x70, 0x35, 0x2c,
+ 0x8c, 0x3f, 0x2d, 0x34, 0x1a, 0xb1, 0xe9, 0xd9, 0xe1, 0xe9,
+ 0x08, 0x83, 0x30, 0x8c, 0xae, 0x27, 0x42, 0xdb, 0x7b, 0x42,
+ 0xc5, 0xa8, 0x01, 0x22, 0x71, 0x6f, 0x63, 0xbd, 0xc8, 0xef,
+ 0x89, 0x7c, 0x53, 0x13, 0xba, 0xa8, 0x0b, 0x4f },
+ { 0x88, 0x54, 0x86, 0xdf, 0x3e, 0xc4, 0x5e, 0xf0, 0xe4, 0x68,
+ 0xed, 0x5f, 0x04, 0x9a, 0x69, 0x17, 0xbb, 0xd3, 0xb0, 0x81,
+ 0x8a, 0x95, 0x40, 0xc2, 0x5c, 0xc2, 0x28, 0x21, 0x76, 0x8a,
+ 0xd9, 0x9a, 0xf8, 0x72, 0x9b, 0xc0, 0xea, 0xce, 0x64, 0xc9,
+ 0xac, 0x39, 0x04, 0xe4, 0xc9, 0xcf, 0x34, 0x65, 0xdb, 0x9a,
+ 0x59, 0x84, 0xbb, 0x1f, 0xf9, 0x4d, 0xd1, 0x43, 0xb2, 0xda,
+ 0x4a, 0x4c, 0x5e, 0x89, 0x7b, 0x0c, 0x46, 0xcd, 0x7c, 0x1b,
+ 0x7d, 0xfd, 0x1b, 0x71, 0x85, 0xcf, 0x08, 0x86, 0x87, 0x73,
+ 0xec, 0x49, 0x74, 0x21, 0x5b, 0x60, 0x0f, 0x33, 0x4e, 0xee,
+ 0x44, 0x19, 0x61, 0x18, 0xa1, 0xf5, 0xab, 0xde, 0xb0, 0x33,
+ 0xe3, 0x03, 0x1b, 0xec, 0xc0, 0x1e, 0xeb, 0xbd, 0x27, 0x1e,
+ 0xc6, 0x12, 0x68, 0x56, 0xc1, 0x64, 0x33, 0xab, 0x33, 0x88,
+ 0xdc, 0x4b, 0xa3, 0xfb, 0xa0, 0x23, 0x70, 0x56 },
+ { 0x31, 0xce, 0xcf, 0xe8, 0xd4, 0xab, 0x96, 0x2d, 0xc5, 0xdd,
+ 0x4d, 0x3e, 0xc9, 0x1f, 0xf9, 0xd7, 0x29, 0x08, 0x32, 0x87,
+ 0xaa, 0xa4, 0xce, 0x0c, 0x33, 0xd8, 0x16, 0x97, 0xf1, 0x19,
+ 0xd6, 0xe0, 0x4d, 0x0e, 0x8b, 0xcf, 0x99, 0x4f, 0xc5, 0x03,
+ 0x1a, 0x0b, 0x96, 0xe4, 0x0f, 0x81, 0xf9, 0x1c, 0x98, 0xb5,
+ 0xd0, 0xab, 0x18, 0x5e, 0xae, 0x19, 0x29, 0xe1, 0x1a, 0xa2,
+ 0x68, 0x85, 0xe6, 0xb9, 0xbc, 0xb0, 0xe8, 0xa2, 0x71, 0xd3,
+ 0x68, 0x10, 0x9e, 0x24, 0x96, 0x0f, 0x1a, 0x1b, 0x73, 0xc6,
+ 0x76, 0x07, 0xdd, 0x08, 0x55, 0xef, 0x8d, 0xef, 0xac, 0xa6,
+ 0x9a, 0xe8, 0x24, 0x1e, 0xe8, 0xff, 0x20, 0x55, 0xa3, 0x1b,
+ 0x19, 0xfe, 0x33, 0x39, 0xcc, 0xb0, 0x07, 0x0b, 0x32, 0x5b,
+ 0xe3, 0x24, 0x3d, 0xb2, 0x71, 0x9f, 0x25, 0xa7, 0xb4, 0x51,
+ 0x6a, 0x94, 0x2c, 0x93, 0x4b, 0xdf, 0xf4, 0x64 },
+ { 0x69, 0x61, 0xb4, 0x6a, 0xda, 0x25, 0x47, 0xb3, 0x5d, 0x8f,
+ 0x3c, 0xf0, 0x9a, 0x6a, 0x4e, 0xc3, 0x11, 0xb0, 0x86, 0x3b,
+ 0xd6, 0xd6, 0xf1, 0xd2, 0x72, 0xfe, 0xfc, 0x05, 0x75, 0xd9,
+ 0xcb, 0x3d, 0x2b, 0x7c, 0x79, 0x45, 0xff, 0x32, 0x52, 0xf8,
+ 0x65, 0xff, 0xa5, 0xf6, 0x6c, 0x74, 0x2a, 0xc4, 0x48, 0x0e,
+ 0xd4, 0xfb, 0xc5, 0x51, 0x6c, 0xa9, 0xf5, 0x02, 0xf6, 0x6d,
+ 0xec, 0xd6, 0xfa, 0x3d, 0x83, 0x9a, 0xa7, 0xbd, 0xc9, 0xd2,
+ 0x0f, 0xf1, 0x10, 0x09, 0xc0, 0xd9, 0xb4, 0xfb, 0xb5, 0x9c,
+ 0x98, 0x00, 0xa2, 0x3f, 0xae, 0xcd, 0x69, 0x75, 0x96, 0x63,
+ 0xe6, 0xad, 0x5b, 0xb5, 0x23, 0xbd, 0x8e, 0x9d, 0xe8, 0x4d,
+ 0xa3, 0xd0, 0xfa, 0x90, 0xfe, 0x59, 0x02, 0xd4, 0x92, 0x1c,
+ 0x36, 0xa0, 0xe5, 0xdd, 0x32, 0xb3, 0xb1, 0x94, 0x36, 0xdf,
+ 0x43, 0x7b, 0xfd, 0x9a, 0xfc, 0x8b, 0x21, 0xe8 },
+ { 0x6a, 0x63, 0xa9, 0x0c, 0x53, 0x75, 0x52, 0x12, 0x19, 0x64,
+ 0xe2, 0x2f, 0x07, 0x81, 0xaa, 0xd9, 0x89, 0xa9, 0xa3, 0x2e,
+ 0xcd, 0x3f, 0x79, 0x4f, 0xdd, 0xae, 0xc4, 0x2b, 0x73, 0xce,
+ 0x5b, 0xe9, 0x2e, 0x25, 0x4d, 0x9e, 0x36, 0x05, 0x1f, 0x9f,
+ 0x1e, 0xb5, 0x1f, 0x32, 0x54, 0xe8, 0x41, 0x23, 0x69, 0x7e,
+ 0x20, 0xa2, 0x97, 0x07, 0xfa, 0x21, 0xda, 0x78, 0x2d, 0x1d,
+ 0x93, 0x41, 0x3c, 0xa7, 0xd6, 0x71, 0x20, 0xe6, 0xb6, 0x55,
+ 0xaf, 0x5d, 0xf9, 0x78, 0x1e, 0xdd, 0x24, 0x6e, 0x3f, 0xd2,
+ 0x4e, 0x4b, 0x88, 0xed, 0xfb, 0x8c, 0xe1, 0x90, 0xa6, 0xe7,
+ 0x19, 0xfd, 0x9c, 0x6f, 0x40, 0x0e, 0xa1, 0xf9, 0x1d, 0x44,
+ 0x70, 0x9d, 0x54, 0xf0, 0xec, 0xa1, 0x7a, 0x5b, 0xdb, 0x28,
+ 0xa0, 0x4c, 0x1e, 0xd5, 0x54, 0x6b, 0x57, 0xaf, 0x14, 0xd9,
+ 0xd0, 0x7b, 0x58, 0x7e, 0xcb, 0x35, 0xe2, 0xac },
+ { 0x51, 0xed, 0x4a, 0x22, 0xd1, 0x51, 0xd9, 0x0e, 0xff, 0xc8,
+ 0x9f, 0xfd, 0x82, 0x55, 0x29, 0x61, 0xa5, 0x47, 0x64, 0x46,
+ 0x82, 0x35, 0xcd, 0x0b, 0x8c, 0x27, 0xf8, 0x92, 0x86, 0x17,
+ 0xf1, 0x65, 0xc2, 0x0b, 0x93, 0x07, 0x0e, 0x02, 0x1e, 0xd3,
+ 0xa5, 0x3a, 0x81, 0xb3, 0x6e, 0xa5, 0x02, 0xea, 0x80, 0x9b,
+ 0xf0, 0x74, 0xe8, 0x44, 0xa5, 0x76, 0xab, 0xcc, 0x78, 0x13,
+ 0x5c, 0xa4, 0x71, 0xdd, 0xd6, 0xed, 0x58, 0x16, 0x5b, 0xa3,
+ 0xf4, 0xa1, 0x65, 0x88, 0x80, 0xc1, 0x5a, 0x4d, 0x3e, 0x7c,
+ 0xf8, 0x65, 0x80, 0x21, 0x7b, 0x37, 0x0f, 0x7f, 0x08, 0x6a,
+ 0x3c, 0xdf, 0x0c, 0xd6, 0xd2, 0xf6, 0x01, 0x66, 0x77, 0x14,
+ 0x3e, 0xb9, 0x4d, 0x4f, 0xe4, 0xa2, 0x96, 0x72, 0x38, 0x8c,
+ 0x51, 0x9b, 0x2c, 0x01, 0x66, 0x8a, 0xb7, 0x4f, 0x61, 0x08,
+ 0x76, 0x55, 0x4e, 0x00, 0x3d, 0x7a, 0xcb, 0xbb },
+ { 0x2d, 0x69, 0x51, 0xbc, 0x2b, 0x8b, 0x5c, 0xe5, 0x41, 0x73,
+ 0xd9, 0x4a, 0xe9, 0xf4, 0x92, 0x56, 0xeb, 0x7a, 0xfe, 0x26,
+ 0x74, 0xa9, 0x79, 0x3c, 0x0d, 0x5f, 0x6f, 0xb1, 0xd2, 0xd1,
+ 0x69, 0xbf, 0x93, 0xdf, 0x3f, 0x2a, 0xe1, 0xef, 0x97, 0x12,
+ 0xaf, 0x0a, 0x92, 0x60, 0x6c, 0x29, 0xfe, 0x48, 0x7a, 0x87,
+ 0x21, 0x38, 0x23, 0x50, 0x0e, 0xcc, 0x0e, 0x29, 0x71, 0x1f,
+ 0x71, 0x06, 0x61, 0x5e, 0x41, 0xc5, 0x3c, 0xf6, 0x28, 0xce,
+ 0x68, 0x5f, 0x68, 0xfc, 0x32, 0x0c, 0x5e, 0xd7, 0xc8, 0x97,
+ 0xf2, 0xa6, 0x0d, 0x2d, 0x6c, 0xeb, 0x5d, 0x5e, 0xfd, 0x67,
+ 0x48, 0x0e, 0xce, 0x64, 0x3b, 0x9b, 0x75, 0xa7, 0xa0, 0x55,
+ 0xdb, 0x50, 0xbf, 0x7d, 0x3e, 0xf9, 0xbe, 0x15, 0xb5, 0x72,
+ 0x96, 0x5f, 0xea, 0x8d, 0x91, 0xa3, 0xbb, 0x27, 0xca, 0xf2,
+ 0x37, 0xd6, 0x96, 0x3a, 0x44, 0x97, 0x01, 0xb4 },
+ { 0x65, 0xc4, 0x8e, 0x78, 0xe0, 0x8c, 0xc5, 0xf0, 0xa2, 0x4e,
+ 0xba, 0x02, 0x16, 0x5b, 0x3a, 0xee, 0x46, 0x49, 0x04, 0xc1,
+ 0xb8, 0x3b, 0x93, 0xf9, 0x75, 0xc4, 0xd0, 0x89, 0xa7, 0xaf,
+ 0x22, 0x68, 0x0b, 0xad, 0x73, 0x0c, 0xbc, 0xf9, 0x31, 0xa0,
+ 0x32, 0x20, 0x48, 0xb1, 0x44, 0x7b, 0x5e, 0x6d, 0x92, 0x43,
+ 0x53, 0xf5, 0x8b, 0x92, 0xa7, 0x42, 0xd4, 0xb6, 0x4d, 0x78,
+ 0xe7, 0x0e, 0x16, 0x27, 0x83, 0xd9, 0x5d, 0x9c, 0x2b, 0x87,
+ 0x4f, 0x55, 0x82, 0x0a, 0x8f, 0x66, 0x71, 0x1e, 0x71, 0xa0,
+ 0xc7, 0x95, 0xcb, 0x7d, 0xc2, 0x74, 0x35, 0x19, 0x6e, 0x7f,
+ 0xea, 0x3a, 0x0b, 0x0f, 0x42, 0xf1, 0x29, 0x57, 0x34, 0x15,
+ 0xcf, 0xc7, 0x75, 0x18, 0xd4, 0x99, 0x4e, 0x8b, 0x8f, 0x42,
+ 0x9e, 0xee, 0x33, 0x3f, 0x24, 0x8f, 0x86, 0xf4, 0xe1, 0x09,
+ 0xdd, 0x00, 0x7d, 0x9f, 0x90, 0x4e, 0x22, 0x2e },
+ { 0x36, 0xb5, 0xcd, 0x2c, 0x7a, 0x6b, 0x22, 0x6f, 0xf6, 0x3d,
+ 0xd9, 0xff, 0xd4, 0x38, 0xba, 0x2d, 0x40, 0x2d, 0x57, 0x85,
+ 0xa8, 0xd9, 0xa3, 0xcb, 0xe2, 0x28, 0x0f, 0xa6, 0xef, 0x24,
+ 0x54, 0x45, 0xe1, 0x06, 0xf4, 0x89, 0x08, 0xb0, 0x55, 0x3a,
+ 0xd8, 0x28, 0x67, 0xed, 0xb2, 0x89, 0x5d, 0x2e, 0xf0, 0x6f,
+ 0x0a, 0x46, 0x25, 0xe7, 0xec, 0xe0, 0x38, 0x09, 0xfa, 0x28,
+ 0x07, 0xd3, 0xe0, 0x13, 0x76, 0xa3, 0xf2, 0xd1, 0x10, 0xf1,
+ 0x8d, 0x12, 0xdb, 0xf6, 0x7f, 0x0b, 0x4d, 0x31, 0x88, 0xc0,
+ 0xf5, 0x4d, 0x3e, 0xee, 0x94, 0x73, 0x51, 0x07, 0xfb, 0x1c,
+ 0x58, 0x1c, 0x31, 0x20, 0x4c, 0xef, 0x28, 0x4a, 0xdf, 0x8f,
+ 0x59, 0xfc, 0xec, 0x77, 0x03, 0x01, 0xcb, 0x14, 0xb2, 0x14,
+ 0x3b, 0x06, 0x56, 0x83, 0xd8, 0xcd, 0xfc, 0xea, 0x23, 0xb4,
+ 0x1a, 0x1c, 0x73, 0xce, 0xde, 0x22, 0x2c, 0x22 },
+ { 0x08, 0xd7, 0xc1, 0x44, 0xdb, 0x39, 0xbf, 0xd8, 0x06, 0x92,
+ 0xf4, 0xc5, 0x39, 0xa5, 0x1d, 0xc8, 0xd2, 0x7c, 0xc9, 0x60,
+ 0xf7, 0x44, 0x5e, 0x8a, 0x18, 0xf7, 0x3c, 0xaf, 0x52, 0x23,
+ 0x89, 0xff, 0x45, 0x59, 0x3d, 0xf1, 0x37, 0x6a, 0x9a, 0xb6,
+ 0x14, 0xe1, 0x82, 0xa7, 0x93, 0xcf, 0x99, 0xc4, 0xff, 0x50,
+ 0x15, 0x1e, 0xea, 0xa7, 0x4d, 0xf8, 0x8d, 0x0e, 0x85, 0xf9,
+ 0x36, 0xa5, 0x1a, 0x37, 0xc6, 0xa2, 0x1d, 0x11, 0x2f, 0x41,
+ 0x22, 0x44, 0x74, 0x83, 0x97, 0x79, 0x0c, 0xc2, 0xe8, 0x10,
+ 0x74, 0x50, 0x19, 0x83, 0x78, 0x1a, 0x67, 0x8a, 0x0d, 0x47,
+ 0x5d, 0x79, 0x8d, 0x93, 0x5a, 0x5e, 0xa1, 0x9e, 0xaf, 0x39,
+ 0xc8, 0x5a, 0xf1, 0xa3, 0x90, 0xa3, 0x57, 0xfa, 0x9b, 0x45,
+ 0x9c, 0xd8, 0x64, 0xd8, 0x0b, 0x41, 0x45, 0x20, 0xc7, 0x50,
+ 0x87, 0xff, 0x4e, 0x20, 0x54, 0x56, 0x79, 0xa7 },
+ { 0x5f, 0x2a, 0xa8, 0xee, 0xba, 0xb7, 0x02, 0x02, 0x8e, 0x2c,
+ 0x38, 0x79, 0x04, 0x00, 0x4a, 0xd9, 0x1d, 0x30, 0x50, 0xae,
+ 0xb5, 0xee, 0x14, 0x7b, 0x4c, 0x38, 0x5e, 0x8b, 0xc7, 0x36,
+ 0x7d, 0x1f, 0xb5, 0x90, 0x52, 0x64, 0x0f, 0x9b, 0x2b, 0x49,
+ 0xf3, 0xfe, 0x9c, 0x42, 0xbb, 0x0c, 0xd2, 0xbf, 0x01, 0x97,
+ 0x24, 0x3e, 0xe3, 0x47, 0x69, 0x4a, 0x3f, 0xe1, 0xe8, 0xb5,
+ 0x89, 0x83, 0x08, 0xe3, 0x95, 0xe9, 0x5b, 0xb8, 0xa8, 0xde,
+ 0x7a, 0xa4, 0x7c, 0xc6, 0xe8, 0x38, 0x5f, 0xce, 0x17, 0xbd,
+ 0xf3, 0xc1, 0xa1, 0x01, 0x61, 0x30, 0xa4, 0xc6, 0x7a, 0x96,
+ 0x6d, 0x8b, 0xd1, 0x58, 0x7b, 0x7e, 0x77, 0x31, 0x23, 0x74,
+ 0x2a, 0x67, 0x8c, 0xdf, 0xf0, 0xec, 0xcd, 0x74, 0xdb, 0x6b,
+ 0xd6, 0x41, 0x87, 0xea, 0x91, 0x92, 0xd4, 0x8c, 0x21, 0x56,
+ 0x80, 0x9c, 0x0d, 0x96, 0x3e, 0xcc, 0xa7, 0x73 },
+ { 0x62, 0x50, 0x1a, 0x98, 0xb4, 0x6f, 0xf9, 0x49, 0xa3, 0x16,
+ 0x49, 0x80, 0x83, 0xc9, 0xf2, 0x24, 0xe8, 0x84, 0xac, 0x76,
+ 0x78, 0x4b, 0xe8, 0x2f, 0xd9, 0xff, 0x03, 0x40, 0x02, 0xbc,
+ 0xd3, 0xc7, 0xc2, 0x82, 0x78, 0xb4, 0x86, 0x6e, 0x5a, 0xe8,
+ 0x59, 0xdc, 0x52, 0xe6, 0x1e, 0xa6, 0xf0, 0x6e, 0xed, 0xcf,
+ 0x2d, 0x1a, 0xe2, 0xd9, 0xd3, 0x86, 0x95, 0x9a, 0xfc, 0xba,
+ 0x8e, 0x2d, 0x85, 0xd1, 0x2b, 0xab, 0xb2, 0x7e, 0x18, 0xbe,
+ 0x05, 0xf6, 0x7d, 0xab, 0xa1, 0x27, 0x05, 0xeb, 0x67, 0xb8,
+ 0x26, 0xf6, 0xee, 0x3b, 0x0f, 0xcb, 0x53, 0x4c, 0xef, 0x34,
+ 0x9c, 0x61, 0xc6, 0x82, 0xe4, 0xd6, 0x0a, 0x69, 0xe8, 0xd3,
+ 0xe6, 0x42, 0xdd, 0x46, 0xa5, 0xaa, 0x68, 0x5e, 0xda, 0x10,
+ 0x6e, 0xbf, 0xb7, 0xbf, 0x38, 0x80, 0xd0, 0xa1, 0x9f, 0x66,
+ 0xe2, 0x08, 0xd4, 0x64, 0x12, 0x66, 0x52, 0x4b },
+ { 0x49, 0x7b, 0x15, 0xfe, 0xfd, 0x3f, 0xc6, 0x65, 0xcc, 0x9c,
+ 0x5f, 0x73, 0xa1, 0xf3, 0x53, 0x1a, 0xab, 0xaa, 0x4c, 0x49,
+ 0xc0, 0xde, 0xa5, 0x86, 0x78, 0x49, 0x9b, 0x73, 0x91, 0xf9,
+ 0xda, 0x5e, 0xd1, 0xac, 0xf7, 0xa0, 0xb5, 0xc4, 0xeb, 0x10,
+ 0xfd, 0x74, 0x10, 0x1c, 0x9a, 0x6f, 0xea, 0x8a, 0x51, 0x9d,
+ 0x21, 0x33, 0xd5, 0x9b, 0x17, 0x41, 0xbd, 0x9a, 0x8e, 0x31,
+ 0x4f, 0x0d, 0x1b, 0x70, 0x52, 0xfb, 0xf5, 0x4d, 0xce, 0xcc,
+ 0xfe, 0x77, 0x62, 0x28, 0x06, 0xe0, 0x2e, 0xa8, 0xab, 0xd3,
+ 0x81, 0x30, 0xc9, 0xb0, 0xed, 0x55, 0x3e, 0xac, 0xfa, 0x3c,
+ 0x91, 0x97, 0x20, 0xaa, 0x45, 0x36, 0xa2, 0x88, 0xda, 0xc8,
+ 0x46, 0xe6, 0x4b, 0x19, 0xe8, 0x25, 0x30, 0x02, 0x8c, 0x8d,
+ 0x3d, 0x67, 0xca, 0x6a, 0x33, 0xdb, 0xa5, 0xe0, 0xe4, 0xbd,
+ 0x56, 0x3f, 0x7d, 0x9a, 0xad, 0x26, 0x40, 0x86 },
+ { 0x18, 0xd4, 0x6a, 0x6c, 0x9e, 0x51, 0x4c, 0xb7, 0xb7, 0xae,
+ 0x7e, 0x5c, 0x2f, 0xf6, 0x37, 0xe6, 0xc2, 0xee, 0xbd, 0x13,
+ 0xed, 0xea, 0x10, 0x71, 0xda, 0xfa, 0x33, 0xfe, 0x06, 0x80,
+ 0x12, 0xca, 0x40, 0x5d, 0x3e, 0x84, 0xd6, 0x30, 0x8e, 0xdc,
+ 0xdd, 0x8d, 0xff, 0xbf, 0x86, 0xa9, 0xb7, 0xce, 0x2a, 0x80,
+ 0xd0, 0xd2, 0x42, 0xc0, 0x07, 0xf4, 0x99, 0xaa, 0x68, 0xac,
+ 0xba, 0x3e, 0xbd, 0x91, 0x8f, 0x31, 0xf0, 0x44, 0x3e, 0x21,
+ 0x6d, 0xbf, 0x9c, 0xd0, 0x6d, 0x31, 0xca, 0x90, 0xf0, 0x2e,
+ 0x81, 0x09, 0xfc, 0x75, 0xa2, 0x9c, 0x53, 0x9f, 0x8c, 0x8c,
+ 0xdb, 0xa2, 0x02, 0xa0, 0xf5, 0xb4, 0xc8, 0x65, 0x22, 0xf8,
+ 0x4a, 0xc3, 0x7d, 0xa9, 0xdb, 0xb0, 0x3d, 0xd3, 0x9a, 0xb2,
+ 0x53, 0x9a, 0xf4, 0x91, 0xa0, 0xfe, 0xc7, 0x19, 0x2a, 0x6f,
+ 0x8a, 0x56, 0xcb, 0xaa, 0xf4, 0x55, 0x68, 0xe9 },
+ { 0x55, 0x04, 0x46, 0x01, 0xd3, 0xf6, 0x2e, 0x40, 0x69, 0xe6,
+ 0xf8, 0xe4, 0x5a, 0x38, 0xfe, 0xf9, 0x10, 0xd5, 0x4f, 0x8a,
+ 0x7e, 0x93, 0x05, 0x0d, 0x45, 0xf9, 0x3d, 0x41, 0xa0, 0x6e,
+ 0x70, 0x8c, 0x3f, 0x0d, 0xb5, 0xcd, 0x7b, 0xb5, 0xe7, 0x51,
+ 0x37, 0x0d, 0xe9, 0xc8, 0xdc, 0xd7, 0x05, 0xad, 0x14, 0x10,
+ 0x9d, 0x29, 0x7c, 0x29, 0x54, 0xf3, 0xab, 0x0b, 0x36, 0xf9,
+ 0xd8, 0x51, 0x76, 0xac, 0x70, 0xeb, 0x06, 0x03, 0x6d, 0xa7,
+ 0xa5, 0x2b, 0x74, 0x07, 0xa7, 0x88, 0xb1, 0x41, 0x71, 0xb9,
+ 0x6c, 0xfe, 0x05, 0x71, 0x13, 0xac, 0x73, 0x45, 0x2e, 0x0d,
+ 0x83, 0x25, 0xa3, 0x25, 0xfd, 0x40, 0xac, 0x0a, 0xbc, 0xda,
+ 0xb4, 0xce, 0xb4, 0xe4, 0xc4, 0xeb, 0x2f, 0x3e, 0x42, 0xae,
+ 0x8a, 0xdd, 0x07, 0x45, 0xdd, 0xb2, 0x49, 0x7c, 0xba, 0xf4,
+ 0x86, 0x8c, 0xbb, 0x22, 0xa7, 0x8b, 0x78, 0x02 },
+ { 0x0d, 0xa3, 0x13, 0xfc, 0xd7, 0xb0, 0xec, 0x4f, 0x56, 0x3a,
+ 0x8f, 0xf7, 0xc6, 0xf5, 0xd7, 0xdb, 0xf3, 0x42, 0x52, 0x09,
+ 0x3d, 0xd7, 0x9f, 0x93, 0xa1, 0x21, 0x18, 0xac, 0x9a, 0x2b,
+ 0xd0, 0x1b, 0x27, 0x07, 0x41, 0x76, 0xf5, 0x32, 0x97, 0x3f,
+ 0x47, 0x7c, 0xa3, 0xdb, 0x9f, 0xf1, 0x00, 0xbc, 0xbc, 0xb5,
+ 0x31, 0x89, 0x70, 0xc2, 0xae, 0xe3, 0xe2, 0x22, 0x0e, 0x85,
+ 0x9a, 0xee, 0xfe, 0x98, 0x33, 0x65, 0xc8, 0xe5, 0x29, 0xad,
+ 0x51, 0x66, 0x90, 0x42, 0x59, 0x6b, 0x91, 0x79, 0x2e, 0x6b,
+ 0x1c, 0xde, 0x06, 0xe7, 0x40, 0x0d, 0x14, 0x4f, 0x1d, 0x21,
+ 0xfb, 0xfa, 0x29, 0x51, 0xfc, 0x83, 0x39, 0x72, 0x1f, 0xfe,
+ 0x29, 0xad, 0x5f, 0x82, 0x7c, 0xd8, 0x66, 0x3e, 0x11, 0x23,
+ 0x6f, 0xb8, 0x54, 0x20, 0x74, 0xd7, 0x41, 0xd0, 0x00, 0x14,
+ 0xd1, 0xc5, 0xc9, 0x10, 0x06, 0xcb, 0x9c, 0xc9 },
+ { 0x63, 0x63, 0x0b, 0xe8, 0xdb, 0x41, 0x4a, 0xcc, 0x62, 0x02,
+ 0x30, 0xd8, 0x1e, 0x82, 0x29, 0x0e, 0x44, 0x16, 0x74, 0x10,
+ 0xa1, 0x16, 0x2d, 0x03, 0x50, 0x94, 0x0c, 0x26, 0x94, 0x1c,
+ 0x25, 0x54, 0xad, 0xfa, 0xe4, 0xe1, 0x73, 0x10, 0x83, 0xef,
+ 0x6d, 0x7c, 0x2e, 0xa0, 0xf8, 0x70, 0x46, 0x64, 0xe2, 0x95,
+ 0x9b, 0xea, 0x09, 0xc2, 0x8f, 0x27, 0x3a, 0xf0, 0xec, 0xbb,
+ 0xca, 0x3d, 0xe5, 0x0c, 0x47, 0x3d, 0x50, 0xd6, 0x1f, 0x1b,
+ 0x7f, 0x00, 0x4d, 0x29, 0xa6, 0x16, 0xf0, 0x3d, 0x06, 0x60,
+ 0xd5, 0x53, 0x1a, 0x0d, 0x04, 0x9a, 0xea, 0xc2, 0x2d, 0x2b,
+ 0xf4, 0xff, 0xc9, 0xe2, 0xce, 0x18, 0x0d, 0x3e, 0x9a, 0x74,
+ 0x7c, 0xb0, 0x04, 0x2a, 0x48, 0x71, 0x39, 0x94, 0x67, 0xb8,
+ 0xa8, 0x23, 0xca, 0x21, 0xd7, 0x0c, 0x00, 0x89, 0x3e, 0x9c,
+ 0x37, 0x12, 0x5a, 0x8c, 0x15, 0xaa, 0x25, 0x57 },
+ { 0x30, 0x6a, 0x98, 0x71, 0xf1, 0x66, 0x88, 0xed, 0x29, 0x58,
+ 0x45, 0xc0, 0x68, 0x54, 0x4e, 0xb0, 0x68, 0x07, 0x4f, 0x37,
+ 0xd5, 0xe5, 0xaa, 0x72, 0xeb, 0x0c, 0xd4, 0x78, 0xf8, 0xac,
+ 0x8f, 0x89, 0xfc, 0xe5, 0x18, 0x6c, 0xe5, 0x58, 0xf6, 0xbe,
+ 0x36, 0x9b, 0x3e, 0x98, 0xbb, 0x44, 0x3c, 0x07, 0x56, 0xae,
+ 0xaf, 0xa8, 0x5a, 0x14, 0x36, 0xfa, 0x3d, 0x4f, 0xd9, 0x77,
+ 0x26, 0x1d, 0x1b, 0x79, 0xca, 0x3d, 0x70, 0x25, 0x58, 0xe2,
+ 0x60, 0x6d, 0x1f, 0x69, 0xb2, 0x0c, 0x13, 0xce, 0xa0, 0x45,
+ 0x9d, 0x99, 0x7d, 0x18, 0xb4, 0xb7, 0x0c, 0x4c, 0xbf, 0x3f,
+ 0x38, 0xf4, 0x49, 0xb9, 0xdc, 0x38, 0x88, 0x3e, 0x04, 0xd6,
+ 0xde, 0x2c, 0x59, 0xad, 0x1b, 0x4d, 0x33, 0xdd, 0x6c, 0x40,
+ 0x2d, 0x89, 0x49, 0xe7, 0x58, 0x23, 0xeb, 0x62, 0xf8, 0x79,
+ 0xbf, 0x8d, 0x52, 0x22, 0x8a, 0x7d, 0x2e, 0x41 },
+ { 0x28, 0x33, 0xac, 0x41, 0xe8, 0x10, 0x3e, 0x37, 0x64, 0x43,
+ 0xeb, 0xe0, 0x58, 0xe5, 0x7c, 0xd4, 0x71, 0xab, 0xa7, 0x31,
+ 0x93, 0xc9, 0xd5, 0x88, 0x93, 0x06, 0x21, 0x5b, 0x77, 0xf4,
+ 0xc0, 0x1c, 0x55, 0x1e, 0x7a, 0x17, 0x6e, 0x72, 0xa1, 0x3d,
+ 0xf9, 0xfa, 0x62, 0x8d, 0x1b, 0xea, 0xa5, 0x11, 0xf6, 0xd4,
+ 0x18, 0xf8, 0x82, 0x07, 0x5f, 0x91, 0xc0, 0x75, 0xc7, 0x01,
+ 0xf5, 0x32, 0x70, 0x1b, 0x28, 0xe6, 0xf6, 0x31, 0x82, 0xa9,
+ 0xd2, 0x2b, 0x4a, 0xf2, 0x2b, 0xc0, 0x0a, 0xc9, 0xc2, 0xde,
+ 0x60, 0xe5, 0x64, 0xd8, 0xc7, 0xaf, 0xb8, 0x99, 0x35, 0x28,
+ 0x32, 0x38, 0x9a, 0x2d, 0x60, 0x23, 0x87, 0xb6, 0xef, 0x20,
+ 0xc5, 0xbf, 0xee, 0x67, 0xa9, 0xbe, 0x01, 0x52, 0xc0, 0xdb,
+ 0x41, 0x20, 0x1e, 0xdf, 0x27, 0xca, 0x0e, 0x6f, 0x65, 0x8f,
+ 0xbc, 0x45, 0x1e, 0x9d, 0x63, 0x4e, 0xc1, 0x36 },
+ { 0x12, 0x0c, 0xd4, 0x54, 0xa4, 0x9d, 0x63, 0x03, 0x67, 0x30,
+ 0x20, 0xed, 0x0b, 0xcf, 0x35, 0x38, 0xbd, 0x59, 0xc7, 0x57,
+ 0xde, 0x5c, 0x01, 0x91, 0x65, 0x5b, 0xa9, 0xe4, 0x08, 0x77,
+ 0x87, 0xd9, 0xe1, 0xdc, 0xbc, 0xd6, 0x99, 0x76, 0x32, 0x7e,
+ 0xf4, 0x2f, 0xaa, 0x97, 0x20, 0x6b, 0x5f, 0xaa, 0xc0, 0x9c,
+ 0x1c, 0x5a, 0x47, 0x22, 0xb4, 0xd7, 0xec, 0xb6, 0x8b, 0xd1,
+ 0x04, 0xba, 0xa4, 0x31, 0x1b, 0x87, 0xa5, 0x8e, 0x13, 0x93,
+ 0xc6, 0xe6, 0xd5, 0xf3, 0x23, 0xf8, 0x27, 0x32, 0x04, 0x49,
+ 0x7d, 0x5a, 0x27, 0x00, 0xdc, 0xfa, 0x19, 0x41, 0xb4, 0x38,
+ 0xe4, 0xcf, 0xfd, 0xc6, 0x03, 0x39, 0x35, 0x12, 0xaf, 0xe7,
+ 0x9d, 0x34, 0x3d, 0xc2, 0x9d, 0x7c, 0x1f, 0x0b, 0x8c, 0x57,
+ 0xa7, 0x28, 0xac, 0x3d, 0x9d, 0xa8, 0x1c, 0x08, 0xdb, 0x24,
+ 0x7e, 0x56, 0x4b, 0x86, 0x8d, 0xa5, 0xec, 0x5c },
+ { 0x02, 0x1c, 0xfd, 0x16, 0x7f, 0xde, 0xea, 0x3e, 0x8e, 0xf1,
+ 0x67, 0x7e, 0x70, 0x19, 0x33, 0x6e, 0xd5, 0x69, 0x84, 0x96,
+ 0xeb, 0x40, 0x54, 0xbc, 0x15, 0x1f, 0x69, 0x3a, 0x9b, 0xe0,
+ 0x24, 0x30, 0xa6, 0x7a, 0xd9, 0xf6, 0x8f, 0x01, 0x03, 0xcb,
+ 0x75, 0x8d, 0xaf, 0x64, 0x5e, 0xb3, 0x3e, 0x34, 0x66, 0xda,
+ 0xe2, 0xc2, 0xd4, 0x67, 0xfa, 0x92, 0xde, 0x1f, 0xaa, 0x12,
+ 0x0b, 0xc9, 0xae, 0xc1, 0x2e, 0xf0, 0x5b, 0x4b, 0x0e, 0x93,
+ 0xdf, 0xf2, 0xbd, 0x16, 0xf5, 0x58, 0x29, 0xdb, 0xdd, 0xcd,
+ 0xef, 0x2f, 0xf3, 0x80, 0x21, 0xa4, 0xf0, 0xd3, 0x3d, 0xe4,
+ 0x87, 0xf0, 0x47, 0x21, 0xab, 0x5c, 0x64, 0x2e, 0xd3, 0xa6,
+ 0x9b, 0x95, 0x77, 0x74, 0x9b, 0x6a, 0x68, 0x41, 0x5a, 0x8d,
+ 0x06, 0x65, 0xbc, 0x00, 0x3e, 0xf0, 0x2c, 0xce, 0x58, 0xee,
+ 0xeb, 0xfd, 0xb8, 0xf4, 0xca, 0xb0, 0xf9, 0xee },
+ { 0x07, 0x26, 0x5b, 0x46, 0xc7, 0x3c, 0xf7, 0x8e, 0x71, 0xed,
+ 0xcd, 0x9c, 0xa2, 0x05, 0x95, 0xa3, 0x5d, 0xed, 0xc2, 0x31,
+ 0xeb, 0x12, 0x8b, 0xb6, 0x80, 0x7c, 0x22, 0xdf, 0xbf, 0x8e,
+ 0xd5, 0x9c, 0xc8, 0x8f, 0xa8, 0x17, 0xfd, 0x0a, 0xe2, 0x8a,
+ 0xdc, 0x0c, 0x7e, 0x57, 0x99, 0x74, 0x30, 0x2c, 0xaf, 0x86,
+ 0xe3, 0x91, 0xed, 0x2a, 0xb5, 0x1a, 0xb9, 0x7a, 0xd5, 0xf9,
+ 0x22, 0x4a, 0x47, 0x0f, 0xfa, 0xeb, 0x52, 0xef, 0x15, 0x60,
+ 0x08, 0xb5, 0x52, 0x67, 0x07, 0x3f, 0x66, 0x34, 0x3d, 0x5a,
+ 0x0d, 0x8f, 0x71, 0x7e, 0x3d, 0x3b, 0xb1, 0x8b, 0xfd, 0xb1,
+ 0x67, 0x76, 0x30, 0x4a, 0xe4, 0xca, 0x1e, 0x5e, 0xc7, 0xb7,
+ 0x0f, 0x39, 0x93, 0xc8, 0x55, 0x36, 0x8d, 0x10, 0xf2, 0xcf,
+ 0x77, 0x13, 0x70, 0x3b, 0xde, 0x37, 0xd6, 0x4a, 0xd2, 0x54,
+ 0x5c, 0x73, 0x71, 0x5f, 0xdf, 0x5c, 0x36, 0xf3 },
+ { 0x36, 0xc5, 0x75, 0x4b, 0x31, 0xd1, 0x49, 0x6c, 0x6e, 0x9d,
+ 0x66, 0x7d, 0x0c, 0xc2, 0xf4, 0xbd, 0x8f, 0x47, 0x57, 0x5d,
+ 0x06, 0x44, 0x08, 0x0e, 0xdd, 0x88, 0xde, 0xee, 0x7a, 0x0a,
+ 0xc6, 0xe9, 0x6d, 0xcc, 0xa4, 0x9b, 0x49, 0xc1, 0x2a, 0xa2,
+ 0xcd, 0x9c, 0x0c, 0x08, 0xad, 0xaf, 0x79, 0x6f, 0x33, 0x3f,
+ 0x27, 0xd0, 0xf8, 0xa4, 0x3a, 0x97, 0x03, 0x89, 0xf3, 0x41,
+ 0x3b, 0xd3, 0x43, 0x02, 0xf8, 0xad, 0xf7, 0x2f, 0x06, 0x95,
+ 0x7b, 0x1f, 0xea, 0x39, 0x9c, 0xaa, 0x25, 0x57, 0x75, 0x3b,
+ 0x55, 0xea, 0x0e, 0x3a, 0x69, 0x73, 0xb9, 0x5a, 0x0e, 0x0e,
+ 0x1b, 0x1a, 0x52, 0x3c, 0x42, 0x8d, 0x23, 0x9e, 0xa8, 0xaa,
+ 0x7a, 0x94, 0x3f, 0x3b, 0xaf, 0x82, 0x6d, 0xfa, 0x5b, 0x86,
+ 0x0f, 0xc4, 0xc5, 0x9a, 0xaf, 0x89, 0xc4, 0x02, 0x77, 0x16,
+ 0x73, 0xdd, 0x99, 0xf0, 0xbd, 0x66, 0x23, 0x2f },
+ { 0x06, 0xfb, 0xf8, 0x61, 0x19, 0x46, 0x94, 0x4e, 0xfc, 0x8a,
+ 0x8a, 0xc9, 0xa2, 0x97, 0x5e, 0xb5, 0xa2, 0xdd, 0xad, 0xe5,
+ 0xc1, 0x64, 0xd9, 0x4f, 0x40, 0xc0, 0x15, 0x32, 0xc9, 0x58,
+ 0x22, 0xde, 0xc0, 0x78, 0x44, 0x94, 0xc4, 0x8a, 0xf5, 0xae,
+ 0x3d, 0x67, 0x42, 0xe9, 0x6b, 0x0b, 0x17, 0x05, 0xa9, 0x4c,
+ 0x3a, 0x40, 0x50, 0x51, 0x3d, 0xed, 0x6c, 0x49, 0x07, 0x5b,
+ 0x37, 0xef, 0x67, 0x77, 0x1c, 0x09, 0xdf, 0xf3, 0xc4, 0x18,
+ 0x00, 0xc5, 0x52, 0x97, 0xda, 0x6b, 0x4b, 0x23, 0xe4, 0xba,
+ 0x1c, 0x18, 0xd0, 0xf7, 0xcd, 0x6d, 0xef, 0x49, 0xc9, 0x05,
+ 0x46, 0x6a, 0x74, 0x0f, 0x8c, 0x79, 0x63, 0x39, 0x84, 0x4a,
+ 0x80, 0x79, 0x97, 0x4e, 0x4b, 0x0e, 0xaf, 0x4e, 0x92, 0x1b,
+ 0x80, 0x55, 0xa6, 0x99, 0x11, 0x22, 0x7e, 0x78, 0x9c, 0x4f,
+ 0x91, 0x20, 0x04, 0x6e, 0xf3, 0x23, 0xd8, 0x4b },
+ { 0x5e, 0x9c, 0xa0, 0xfd, 0x1f, 0x0f, 0xa9, 0xea, 0x5e, 0x64,
+ 0x29, 0x53, 0x04, 0xbb, 0x5a, 0xb1, 0x2a, 0x7d, 0x84, 0x11,
+ 0xa0, 0x3e, 0x8f, 0x0e, 0xd9, 0xd1, 0x96, 0x53, 0xd9, 0x5e,
+ 0xef, 0xa1, 0x83, 0x3d, 0x46, 0xa1, 0x36, 0x19, 0xcf, 0x4d,
+ 0x96, 0xd2, 0xe9, 0x57, 0x9d, 0xa0, 0x79, 0x33, 0x7c, 0x88,
+ 0xb1, 0x0b, 0x23, 0xd3, 0x43, 0x4e, 0xc9, 0x21, 0xe6, 0x9d,
+ 0x95, 0x71, 0xae, 0x28, 0x42, 0x2c, 0x32, 0x6d, 0xf0, 0x66,
+ 0x12, 0xa5, 0xe4, 0x0a, 0xbc, 0x9d, 0x5c, 0xbf, 0x6b, 0xf3,
+ 0x4c, 0x5f, 0x2a, 0x2a, 0xfb, 0x65, 0xbd, 0x03, 0x98, 0x2b,
+ 0x61, 0xf5, 0xb3, 0x0a, 0x1a, 0x23, 0x7b, 0xeb, 0x07, 0x1a,
+ 0xe4, 0xd7, 0x41, 0x7c, 0x05, 0xfe, 0xf5, 0x9b, 0x0f, 0xde,
+ 0xf8, 0xb9, 0xd8, 0x3b, 0x58, 0xc8, 0x1d, 0x04, 0x0f, 0xeb,
+ 0x2d, 0x65, 0x33, 0x8e, 0x3f, 0x45, 0xaa, 0x97 },
+ { 0x94, 0x06, 0x22, 0xb3, 0xc6, 0x83, 0x6a, 0xf8, 0x8c, 0xc2,
+ 0x04, 0x5b, 0x49, 0x95, 0x5f, 0x34, 0x69, 0xb1, 0xf1, 0xc7,
+ 0x36, 0x24, 0x24, 0xa6, 0x75, 0xb3, 0x18, 0xdc, 0x76, 0x93,
+ 0x69, 0x14, 0xd3, 0x39, 0x17, 0x17, 0x06, 0x4d, 0xdc, 0x77,
+ 0xea, 0xcc, 0x55, 0x13, 0x65, 0x64, 0x78, 0xe3, 0x7b, 0xc9,
+ 0x3a, 0x45, 0x03, 0xe3, 0xe0, 0x13, 0x7f, 0x16, 0x5f, 0xd3,
+ 0xa8, 0xf9, 0xac, 0x8a, 0x6a, 0xdc, 0x4b, 0x9e, 0x1e, 0x84,
+ 0x72, 0x8b, 0x26, 0xe3, 0x6f, 0xbe, 0x61, 0xf6, 0x4b, 0x56,
+ 0xfc, 0x79, 0x56, 0x2c, 0xd4, 0x03, 0x4a, 0x9a, 0xc1, 0xfc,
+ 0x9c, 0x7b, 0xc7, 0x58, 0xc6, 0xa3, 0xe9, 0x52, 0xdc, 0x2c,
+ 0x0d, 0x17, 0x46, 0x7c, 0x65, 0xfb, 0x9e, 0xfc, 0xff, 0xdb,
+ 0x0e, 0xb2, 0xe2, 0xda, 0x40, 0xbf, 0xe7, 0x8a, 0x95, 0xa2,
+ 0x5b, 0xd5, 0x45, 0x71, 0x19, 0x7c, 0x5d, 0xc4 },
+ { 0x80, 0xbb, 0x16, 0x64, 0x78, 0x5b, 0xed, 0xb6, 0xb9, 0xf4,
+ 0x98, 0x24, 0xbd, 0xe6, 0xbd, 0x71, 0xe2, 0xb4, 0x9c, 0x8c,
+ 0xcf, 0xde, 0x33, 0x68, 0xd8, 0xa9, 0x98, 0xa4, 0xf1, 0x90,
+ 0xa2, 0xc8, 0x2e, 0x0f, 0x86, 0x08, 0x3c, 0x23, 0xba, 0x9c,
+ 0x1e, 0xf1, 0xea, 0x8a, 0x49, 0x7a, 0x40, 0xda, 0xaf, 0x3f,
+ 0x5d, 0xe2, 0xce, 0xd2, 0xbf, 0x77, 0x69, 0xaa, 0x40, 0x75,
+ 0xae, 0x9c, 0x44, 0xb2, 0x0f, 0x82, 0xb3, 0xa6, 0xad, 0x98,
+ 0x02, 0xb6, 0x47, 0xe9, 0x7d, 0xa8, 0xf0, 0x16, 0x52, 0xa4,
+ 0xde, 0x6d, 0x87, 0x54, 0x6f, 0xc8, 0x3b, 0x11, 0x05, 0x41,
+ 0xaf, 0x9d, 0x3d, 0x26, 0x22, 0x46, 0xc6, 0x32, 0x1e, 0x0a,
+ 0x67, 0x3e, 0x14, 0xa5, 0x8c, 0xf0, 0xc4, 0xd5, 0x5b, 0x97,
+ 0xab, 0xd5, 0x3b, 0x29, 0x62, 0x5d, 0xd3, 0xf8, 0xf1, 0x15,
+ 0x47, 0x10, 0xcc, 0xb7, 0x0d, 0x99, 0x79, 0x73 },
+ { 0x07, 0x7b, 0xa5, 0xea, 0x41, 0x21, 0x23, 0x50, 0xed, 0xfc,
+ 0x15, 0x48, 0x63, 0xb8, 0x5a, 0x35, 0x95, 0x10, 0x79, 0x18,
+ 0x11, 0x0c, 0x77, 0x9c, 0x96, 0x95, 0x98, 0xdd, 0xcc, 0x58,
+ 0x00, 0x0b, 0x64, 0x97, 0x59, 0x63, 0xcb, 0x11, 0x8f, 0xf9,
+ 0x79, 0xea, 0x49, 0xc2, 0x54, 0xe2, 0x9c, 0xdc, 0xcd, 0x65,
+ 0xd2, 0x37, 0x1f, 0x20, 0xb3, 0x22, 0x7d, 0x5a, 0x6f, 0xf6,
+ 0x54, 0xeb, 0x49, 0xff, 0x0b, 0x66, 0xd7, 0x89, 0x76, 0xf8,
+ 0x2d, 0xbd, 0xb6, 0xba, 0x85, 0x00, 0x8b, 0xb4, 0xcb, 0x93,
+ 0xc3, 0xbf, 0xd6, 0xa8, 0x3e, 0x70, 0x86, 0xfa, 0x2f, 0xb9,
+ 0xe0, 0xc3, 0xa2, 0xa7, 0xba, 0x07, 0x9f, 0x15, 0x53, 0xde,
+ 0x13, 0x3b, 0x23, 0x38, 0x46, 0x1e, 0x70, 0xcf, 0x87, 0x93,
+ 0xb2, 0x73, 0x15, 0x5e, 0xe5, 0x61, 0xac, 0x5e, 0x68, 0x83,
+ 0x05, 0xe5, 0x75, 0xfe, 0xfd, 0x14, 0x5c, 0xb5 },
+ { 0x6b, 0x20, 0x06, 0xdf, 0x45, 0x91, 0xa2, 0xe2, 0xba, 0xf7,
+ 0x58, 0x1d, 0x9b, 0xc7, 0x7d, 0x21, 0x5b, 0x3c, 0x81, 0xb2,
+ 0xf4, 0x73, 0x96, 0x53, 0x09, 0x01, 0x26, 0x5c, 0xaf, 0xf0,
+ 0x75, 0x86, 0x81, 0x38, 0x99, 0x5a, 0x52, 0x35, 0x0e, 0x80,
+ 0xc9, 0x31, 0x79, 0xbd, 0xd3, 0xf5, 0x5c, 0x07, 0xab, 0xe5,
+ 0x23, 0x6e, 0x62, 0x99, 0xae, 0x7f, 0x2b, 0xe7, 0x02, 0x0d,
+ 0x45, 0xad, 0x59, 0x20, 0x9d, 0x28, 0x6e, 0xa7, 0x2c, 0xda,
+ 0xde, 0x77, 0xd5, 0x69, 0xaf, 0x36, 0x9a, 0xbf, 0x49, 0xee,
+ 0xd4, 0x6e, 0xc7, 0xe5, 0xf4, 0x64, 0xe8, 0xb3, 0xbb, 0x1d,
+ 0x31, 0xd1, 0x0e, 0x80, 0xc7, 0x60, 0x01, 0xdc, 0x1f, 0x98,
+ 0x8a, 0x32, 0xf1, 0x0f, 0x19, 0x12, 0xed, 0xc5, 0x80, 0x6d,
+ 0x02, 0x72, 0x43, 0x12, 0x14, 0x45, 0x05, 0x02, 0xa0, 0xab,
+ 0x0b, 0x3a, 0x38, 0xd3, 0xcd, 0xd8, 0x6f, 0x61 },
+ { 0x53, 0x21, 0x7e, 0xa6, 0xbd, 0x26, 0xb5, 0x50, 0x85, 0x5b,
+ 0x91, 0x1c, 0x66, 0x86, 0x8a, 0xfc, 0x84, 0x95, 0x40, 0xc0,
+ 0x32, 0xc3, 0x8e, 0x83, 0x24, 0xd1, 0x16, 0xe6, 0x38, 0xd6,
+ 0xb0, 0xa0, 0x26, 0x2a, 0x6f, 0xb8, 0xc9, 0x17, 0xb1, 0x6c,
+ 0xd6, 0xc1, 0x2e, 0x10, 0x62, 0x57, 0x41, 0xa4, 0x5c, 0x8d,
+ 0x7a, 0x75, 0x27, 0x55, 0xf8, 0x94, 0xb4, 0x76, 0xf4, 0x1e,
+ 0x9d, 0xc1, 0x2c, 0xe9, 0x10, 0xd0, 0xcb, 0x97, 0x6f, 0xa8,
+ 0xb7, 0x75, 0x70, 0xa9, 0xf4, 0x0c, 0x15, 0x31, 0xc0, 0x5a,
+ 0x54, 0xf1, 0xa7, 0x01, 0x35, 0x7f, 0x67, 0x9e, 0x4f, 0x8a,
+ 0x61, 0x84, 0xd2, 0x12, 0x5c, 0xaf, 0x84, 0x72, 0x8f, 0x25,
+ 0x53, 0xd5, 0x12, 0x5e, 0xd5, 0x71, 0x8d, 0x33, 0x00, 0x0e,
+ 0x7f, 0x99, 0x93, 0x1f, 0x53, 0x6a, 0x96, 0x2b, 0xb4, 0xfd,
+ 0xb2, 0xfe, 0x50, 0xa8, 0x96, 0x5b, 0x1b, 0xc1 },
+ { 0x03, 0x86, 0x93, 0x1e, 0xd9, 0xad, 0xbe, 0xef, 0x64, 0xbd,
+ 0x60, 0x01, 0x61, 0x83, 0x0a, 0xc2, 0xa0, 0x8d, 0x33, 0x79,
+ 0xf9, 0x78, 0x1b, 0x12, 0x99, 0x89, 0x3d, 0xd0, 0xf2, 0xbd,
+ 0x29, 0x5b, 0xf8, 0xe2, 0xd1, 0x73, 0x60, 0x44, 0xa9, 0xa6,
+ 0xa9, 0xe0, 0x8d, 0xcb, 0x4a, 0x6d, 0x65, 0xa1, 0xc8, 0x1e,
+ 0x01, 0xc9, 0xe9, 0xa0, 0x6f, 0x07, 0xa7, 0x27, 0xda, 0xcc,
+ 0x35, 0xcc, 0x05, 0x2f, 0x0f, 0x93, 0x8d, 0x1e, 0x42, 0xce,
+ 0x9e, 0xa8, 0xc4, 0xfa, 0xe9, 0xe8, 0xc3, 0xd4, 0xb1, 0xe1,
+ 0xa0, 0x7a, 0x96, 0xb3, 0x41, 0xc8, 0x15, 0xef, 0x6d, 0xc3,
+ 0xb8, 0x48, 0x38, 0x1a, 0x4f, 0xf7, 0xab, 0x7d, 0xaa, 0x2d,
+ 0xe4, 0xa5, 0x43, 0x44, 0x96, 0x4e, 0xb8, 0x5e, 0xca, 0xcb,
+ 0xd2, 0x6e, 0x96, 0x8d, 0xa9, 0xcb, 0xe6, 0x21, 0x14, 0x6c,
+ 0xfc, 0x84, 0x04, 0x73, 0x25, 0x9f, 0x52, 0xb4 },
+ { 0x2c, 0xaa, 0xf7, 0x49, 0x15, 0x04, 0x1c, 0x20, 0x0e, 0x49,
+ 0x67, 0xcd, 0xb4, 0xa8, 0x74, 0x8b, 0xcd, 0x3a, 0x21, 0xd6,
+ 0xd5, 0x8c, 0x6d, 0xb8, 0x1b, 0xa0, 0x97, 0xfc, 0xb7, 0x66,
+ 0x86, 0x3d, 0x81, 0xce, 0x36, 0xef, 0x8b, 0xbd, 0xcc, 0xb2,
+ 0x45, 0x9e, 0x93, 0x67, 0xbf, 0x32, 0x0e, 0x0e, 0x82, 0x59,
+ 0x68, 0x87, 0xe5, 0xef, 0x50, 0x2f, 0x67, 0x7e, 0xdc, 0x88,
+ 0x29, 0x72, 0x72, 0x1a, 0x75, 0xba, 0xcd, 0x75, 0x0f, 0x9c,
+ 0x6c, 0x40, 0x41, 0x86, 0x79, 0xfd, 0x49, 0xff, 0xf5, 0xc4,
+ 0x55, 0xcb, 0xe7, 0x09, 0x03, 0x31, 0x6a, 0xd2, 0x35, 0x4f,
+ 0xf4, 0x47, 0x11, 0x15, 0x94, 0xcd, 0x61, 0xca, 0x2e, 0x78,
+ 0x69, 0x9c, 0xe4, 0xd6, 0x3b, 0xc2, 0x38, 0xcf, 0x53, 0x6e,
+ 0xba, 0xed, 0xed, 0x9d, 0x2b, 0x67, 0xe3, 0x55, 0xbb, 0x07,
+ 0xd0, 0xd7, 0xab, 0xb3, 0xd0, 0x98, 0x85, 0xa5 },
+ { 0x86, 0xd7, 0xf5, 0x32, 0x45, 0xfe, 0x3b, 0xd8, 0x65, 0xa1,
+ 0xbb, 0xe2, 0x93, 0x50, 0x36, 0x1e, 0xc7, 0xc7, 0x1f, 0x3d,
+ 0x09, 0xd8, 0xff, 0x91, 0x36, 0xe8, 0x86, 0xe2, 0x70, 0xb0,
+ 0x55, 0x18, 0xb5, 0x6e, 0x45, 0xf1, 0xad, 0x50, 0xd9, 0xd9,
+ 0x6b, 0xb5, 0xd5, 0x11, 0xc1, 0x8a, 0x2b, 0xe7, 0x65, 0x6a,
+ 0x47, 0xca, 0x57, 0xd1, 0xa1, 0x70, 0x11, 0x72, 0x5d, 0x69,
+ 0xab, 0xac, 0x96, 0xf9, 0x30, 0x2c, 0x8f, 0x78, 0xf5, 0x67,
+ 0x23, 0xde, 0xb9, 0x09, 0xd2, 0x32, 0xd9, 0x25, 0xdc, 0xf2,
+ 0x9c, 0xe8, 0xe6, 0x81, 0x2d, 0xf3, 0x1f, 0xa4, 0x6c, 0xa8,
+ 0xb3, 0x20, 0x35, 0x6d, 0x39, 0x82, 0x48, 0xd0, 0xab, 0x75,
+ 0x7a, 0xe5, 0xb7, 0x0b, 0x26, 0x8e, 0xd1, 0xa5, 0x78, 0x1a,
+ 0x8c, 0x86, 0xb3, 0xe4, 0xea, 0x23, 0x22, 0x47, 0x15, 0x45,
+ 0x44, 0xf9, 0x80, 0x06, 0x6e, 0xd2, 0x04, 0x24 },
+ { 0x68, 0x2a, 0x55, 0xe3, 0x86, 0xc0, 0xb4, 0xdd, 0x5a, 0x4c,
+ 0x3c, 0x6f, 0xcb, 0xc1, 0xff, 0x85, 0x52, 0xc9, 0x4d, 0x0f,
+ 0x7d, 0x83, 0x6c, 0x5a, 0x5f, 0xfe, 0x5f, 0x94, 0x3d, 0xb6,
+ 0x08, 0x3c, 0x68, 0xee, 0xea, 0x62, 0xea, 0xe7, 0x5b, 0x16,
+ 0x68, 0xa6, 0x76, 0xdb, 0x88, 0x37, 0xd5, 0x1d, 0x00, 0x7f,
+ 0x3b, 0xaf, 0x24, 0x19, 0x8f, 0xd2, 0x4f, 0x5b, 0x45, 0x39,
+ 0x6e, 0x2b, 0xd8, 0x11, 0x0f, 0xb2, 0x39, 0xa8, 0x57, 0x9b,
+ 0xcc, 0x13, 0x36, 0x9f, 0x3b, 0xd9, 0x83, 0x55, 0xb0, 0x58,
+ 0x58, 0x30, 0x06, 0x44, 0xfb, 0xea, 0x45, 0xb8, 0x4d, 0xa3,
+ 0xb9, 0xdb, 0x88, 0x7e, 0xc6, 0x66, 0xd3, 0xe3, 0xac, 0x54,
+ 0x90, 0x89, 0x8d, 0x1c, 0xfa, 0xe5, 0x0e, 0x52, 0x26, 0xcd,
+ 0x01, 0xb4, 0xb6, 0x97, 0x50, 0x98, 0x8b, 0xc3, 0xd9, 0x13,
+ 0x99, 0xf1, 0x6e, 0xb6, 0xb0, 0xbf, 0x71, 0x9a },
+ { 0x02, 0x22, 0x7f, 0xa6, 0xfe, 0xfe, 0x4d, 0xcd, 0x05, 0x4f,
+ 0x25, 0x42, 0xe4, 0x0d, 0x39, 0x05, 0xd2, 0xcd, 0xf0, 0x1b,
+ 0x76, 0x88, 0xd7, 0x0c, 0xdc, 0xec, 0xc3, 0xab, 0x7b, 0x4c,
+ 0x7c, 0x91, 0xad, 0x73, 0x70, 0x52, 0xc6, 0xfd, 0xd7, 0xa6,
+ 0x41, 0x5d, 0x46, 0xa0, 0x85, 0x2f, 0x76, 0x11, 0x2c, 0xc3,
+ 0x0a, 0x31, 0xff, 0x4b, 0x04, 0x5c, 0x9b, 0xc7, 0xfd, 0x4f,
+ 0x14, 0x52, 0xd0, 0xac, 0x6c, 0x44, 0x76, 0x84, 0x49, 0xcd,
+ 0xc2, 0x1a, 0x15, 0x43, 0xf2, 0x7e, 0x23, 0x24, 0xa6, 0x8b,
+ 0xc8, 0x99, 0x27, 0xe6, 0x8a, 0x87, 0x72, 0x27, 0x1b, 0x13,
+ 0x34, 0x2f, 0x14, 0x29, 0x66, 0x29, 0x89, 0x0d, 0x39, 0x65,
+ 0xec, 0xc3, 0xe5, 0xe7, 0xd6, 0xae, 0x0c, 0xc5, 0xb7, 0x5a,
+ 0x46, 0xe3, 0x22, 0x76, 0x02, 0x6c, 0x34, 0xc7, 0x24, 0x5d,
+ 0xc8, 0xf2, 0x35, 0xa4, 0x58, 0x74, 0x95, 0xaa },
+ { 0x54, 0x7e, 0x24, 0x9a, 0x29, 0x26, 0x97, 0x78, 0x44, 0x6e,
+ 0x6a, 0x62, 0x15, 0xeb, 0xc7, 0xd0, 0x34, 0x27, 0xe5, 0x4d,
+ 0x7d, 0xd3, 0x75, 0x78, 0x64, 0xfc, 0x55, 0xfc, 0x28, 0xff,
+ 0xba, 0x81, 0x97, 0x1e, 0xb9, 0x15, 0xd5, 0xc4, 0xe8, 0x43,
+ 0x5f, 0x37, 0x16, 0xdf, 0xe3, 0x42, 0x0e, 0xea, 0xf5, 0xa5,
+ 0xc2, 0x2e, 0xbb, 0xc9, 0xf1, 0xa5, 0x64, 0xd1, 0x6e, 0x9f,
+ 0x88, 0x11, 0x67, 0xf4, 0xb0, 0x21, 0xe1, 0x4e, 0x07, 0x10,
+ 0xae, 0x9a, 0xbc, 0x1f, 0x27, 0x9d, 0x68, 0xfa, 0x4f, 0xce,
+ 0x21, 0xc9, 0x55, 0xf9, 0x8e, 0x08, 0xcb, 0x04, 0x09, 0x59,
+ 0xd0, 0x44, 0xb4, 0xcb, 0xec, 0xa0, 0x9d, 0x10, 0x90, 0xbf,
+ 0x96, 0xf7, 0xc5, 0xe5, 0xcb, 0x12, 0x8e, 0x09, 0x4f, 0x2c,
+ 0x8b, 0x22, 0x8e, 0xfe, 0xed, 0x46, 0xfd, 0xfd, 0x22, 0x5d,
+ 0x18, 0x05, 0xef, 0xd9, 0xb7, 0x51, 0x94, 0x8b },
+ { 0x45, 0xa4, 0x1c, 0xc0, 0xd2, 0xb0, 0x8e, 0xea, 0xc4, 0x2d,
+ 0xc7, 0x45, 0xbf, 0xe6, 0xc1, 0xeb, 0x1c, 0x68, 0x5c, 0xea,
+ 0x3c, 0x61, 0x32, 0xe6, 0xfc, 0xeb, 0x5c, 0x90, 0x8b, 0xcb,
+ 0x25, 0x05, 0x34, 0x79, 0xbe, 0xa1, 0xc2, 0x20, 0x21, 0x8b,
+ 0x74, 0x75, 0xe0, 0xe8, 0x31, 0x91, 0xd4, 0xe3, 0xd2, 0x45,
+ 0x65, 0x69, 0x79, 0x32, 0xa1, 0xf0, 0xe5, 0x7e, 0x4d, 0x29,
+ 0x61, 0x6f, 0xde, 0xda, 0x7f, 0xfd, 0xdf, 0x84, 0x03, 0xdc,
+ 0xf1, 0xce, 0xa0, 0xc5, 0xbb, 0x1d, 0xdd, 0xee, 0xc0, 0x25,
+ 0x18, 0xc9, 0x9d, 0x83, 0xaa, 0x2f, 0x7d, 0x51, 0x3d, 0x2c,
+ 0x09, 0xba, 0xf9, 0x34, 0x28, 0x23, 0x5b, 0x41, 0x27, 0xea,
+ 0x9d, 0xe5, 0xe7, 0x0a, 0xf6, 0x51, 0x51, 0xe1, 0x0a, 0x63,
+ 0xf3, 0xd8, 0xb4, 0xe6, 0xcd, 0xcc, 0x79, 0x55, 0xcf, 0x50,
+ 0x47, 0x06, 0x86, 0x8a, 0xa1, 0xff, 0xda, 0x27 },
+ { 0x12, 0x87, 0x63, 0xc9, 0x42, 0xee, 0x40, 0xc8, 0xba, 0x85,
+ 0x0a, 0xc9, 0xd0, 0x87, 0xda, 0x02, 0xa8, 0x4c, 0x06, 0xb6,
+ 0xb6, 0xac, 0x2a, 0xf6, 0x36, 0x2d, 0x7a, 0x77, 0xd8, 0x8e,
+ 0x69, 0x44, 0x2d, 0x32, 0x59, 0xd4, 0x8a, 0x0f, 0x29, 0x8c,
+ 0x0f, 0x0b, 0xd9, 0xbd, 0x28, 0xff, 0xf6, 0xdd, 0x14, 0x56,
+ 0x01, 0xed, 0x3d, 0x58, 0x9b, 0xea, 0xc8, 0x7b, 0xe1, 0xe4,
+ 0x49, 0xdf, 0x78, 0x1e, 0x96, 0x32, 0x3d, 0x25, 0x24, 0x21,
+ 0xe3, 0x75, 0xb2, 0xaf, 0xbd, 0xdc, 0x0d, 0xf3, 0x18, 0x4e,
+ 0x93, 0xdf, 0x7d, 0xa4, 0x98, 0x4f, 0xd1, 0x1f, 0x2c, 0x9e,
+ 0x4f, 0x52, 0xa2, 0x85, 0x74, 0x1a, 0x4f, 0x54, 0x12, 0xd2,
+ 0xa9, 0xbe, 0xb1, 0x7e, 0xdc, 0x1e, 0xa7, 0x58, 0x5e, 0xeb,
+ 0x4c, 0x66, 0x41, 0xff, 0x96, 0x2f, 0xa1, 0x7c, 0xf7, 0x0e,
+ 0x3e, 0xa9, 0xb2, 0xc7, 0x4d, 0xbb, 0xf0, 0xe1 },
+ { 0x75, 0xe9, 0x6b, 0xcc, 0xfc, 0x4f, 0x74, 0xd2, 0x1e, 0x82,
+ 0x04, 0xb7, 0x68, 0xbb, 0x63, 0x7f, 0x6a, 0x7e, 0x00, 0x67,
+ 0xb4, 0x12, 0x6d, 0x72, 0x5e, 0x8c, 0xa1, 0xf9, 0xb2, 0x0f,
+ 0xcd, 0x74, 0x7e, 0x8d, 0xa5, 0x13, 0x99, 0xb3, 0xa0, 0xeb,
+ 0x21, 0x60, 0xcb, 0x18, 0xb1, 0x3e, 0xb7, 0x1b, 0x07, 0x36,
+ 0x55, 0x61, 0xb1, 0xc9, 0x95, 0xf3, 0xb4, 0x76, 0x56, 0x5e,
+ 0x03, 0x21, 0x81, 0x23, 0x3f, 0x1d, 0x8d, 0x88, 0xc1, 0xde,
+ 0x7e, 0xbc, 0xfe, 0x9f, 0xda, 0x66, 0x8b, 0x88, 0x17, 0x52,
+ 0x5b, 0x29, 0xd2, 0x13, 0x9a, 0x2e, 0x8e, 0x03, 0x7c, 0x75,
+ 0xf5, 0xc4, 0xcb, 0x08, 0x85, 0x48, 0xb2, 0x11, 0x5d, 0xa3,
+ 0x86, 0x61, 0x57, 0x67, 0xe9, 0x63, 0x1d, 0x14, 0x70, 0xfe,
+ 0xde, 0xd2, 0x7c, 0xc2, 0x00, 0x44, 0x34, 0xb0, 0x8f, 0x6e,
+ 0x29, 0xa8, 0x0f, 0x07, 0xac, 0xba, 0xc1, 0x78 },
+ { 0x30, 0x9a, 0x6e, 0x9a, 0xba, 0x26, 0x89, 0x49, 0xd8, 0x8f,
+ 0x56, 0x6b, 0xa1, 0x6e, 0x52, 0x3d, 0x8a, 0x86, 0xf0, 0x9b,
+ 0x5d, 0x6b, 0x81, 0x96, 0xae, 0xba, 0x4f, 0xe4, 0x8a, 0xe5,
+ 0xb6, 0x87, 0xfe, 0x02, 0xf8, 0x3c, 0xb1, 0x48, 0x76, 0x27,
+ 0x9c, 0x57, 0xb0, 0x29, 0xcf, 0x3d, 0xe4, 0x92, 0x98, 0x5e,
+ 0xf8, 0xd2, 0x42, 0xd1, 0xd9, 0x92, 0xe8, 0x0b, 0x2e, 0x7a,
+ 0xc1, 0x5b, 0x24, 0x89, 0xa7, 0x67, 0x26, 0x83, 0xea, 0x87,
+ 0x6f, 0x48, 0x60, 0x08, 0x3b, 0xd8, 0x81, 0x50, 0x91, 0x29,
+ 0xa9, 0x78, 0x88, 0x36, 0x4f, 0x53, 0xf5, 0x5f, 0x91, 0xd8,
+ 0x5d, 0x46, 0x4d, 0x6f, 0xd5, 0xb7, 0x12, 0xb6, 0xbf, 0x83,
+ 0x6c, 0x07, 0x15, 0x0f, 0x64, 0xa8, 0x46, 0xd1, 0xea, 0x98,
+ 0x7d, 0x2a, 0xdf, 0x58, 0x50, 0x58, 0x7c, 0x38, 0x45, 0x25,
+ 0x18, 0x9d, 0x1f, 0xdc, 0x0d, 0x19, 0x71, 0x6e },
+ { 0x04, 0x58, 0x25, 0x8a, 0xd7, 0x59, 0x37, 0x89, 0xee, 0xb3,
+ 0x66, 0x53, 0x57, 0x69, 0xb2, 0x02, 0xe3, 0x59, 0x78, 0xfd,
+ 0x71, 0x4f, 0xea, 0x55, 0xcf, 0x96, 0x73, 0xc7, 0x75, 0xd6,
+ 0x8a, 0xc1, 0xd4, 0x2e, 0x87, 0x7f, 0xdb, 0x2a, 0x35, 0x8a,
+ 0x92, 0x4d, 0xbe, 0x7d, 0x53, 0xbe, 0x7e, 0xfd, 0xd3, 0x1c,
+ 0xcf, 0xd6, 0x21, 0xc2, 0xb6, 0x3d, 0x26, 0x7f, 0x8d, 0x8f,
+ 0x8e, 0x1e, 0xee, 0x88, 0x0f, 0xbb, 0x17, 0x14, 0x1f, 0xa2,
+ 0x64, 0xe8, 0xa1, 0x5b, 0x33, 0x62, 0xc4, 0x9d, 0x5c, 0xcb,
+ 0xc5, 0x81, 0xef, 0x87, 0xeb, 0x90, 0x86, 0x81, 0xc0, 0xc3,
+ 0xac, 0xdb, 0x75, 0x50, 0xed, 0x3a, 0x8f, 0xa1, 0x5a, 0x85,
+ 0xbe, 0xd3, 0x6c, 0xc5, 0xcc, 0x7b, 0xeb, 0x01, 0x7f, 0xe0,
+ 0x9f, 0x5c, 0x1a, 0x5f, 0xe7, 0x0f, 0xb8, 0xc5, 0x0c, 0x4d,
+ 0xef, 0x27, 0xee, 0x50, 0xbd, 0xfb, 0xe9, 0x7a },
+ { 0x53, 0xf4, 0xa3, 0xe0, 0x95, 0xb7, 0x73, 0x58, 0xa2, 0xb8,
+ 0x80, 0xe5, 0x6f, 0x86, 0xc0, 0x29, 0x00, 0x4b, 0x87, 0x57,
+ 0xe4, 0x1f, 0xac, 0xc0, 0xba, 0xaf, 0x66, 0x3c, 0x96, 0xd1,
+ 0x09, 0x91, 0x7f, 0x74, 0x91, 0x5b, 0x2e, 0x84, 0xec, 0x34,
+ 0xbe, 0xe1, 0x48, 0x43, 0x4f, 0x02, 0x90, 0x4b, 0x83, 0xc8,
+ 0xf6, 0xa6, 0xe7, 0xb6, 0xd8, 0x86, 0xc0, 0x89, 0x5b, 0xff,
+ 0x39, 0x77, 0x7e, 0x00, 0xb3, 0x5f, 0xce, 0x26, 0xd6, 0xb3,
+ 0xc7, 0x42, 0x98, 0xc0, 0x56, 0x58, 0x43, 0x34, 0x6b, 0x9c,
+ 0xe0, 0xee, 0x85, 0x1d, 0xa3, 0x07, 0x67, 0xc3, 0xf5, 0x6a,
+ 0x8d, 0xef, 0x0f, 0x0e, 0x6b, 0x5f, 0x28, 0x5d, 0x67, 0x45,
+ 0xca, 0x2e, 0x89, 0x2e, 0x0e, 0x66, 0xcb, 0xa7, 0x0d, 0x2e,
+ 0x66, 0x57, 0x2d, 0x40, 0x58, 0x57, 0x57, 0x79, 0xdf, 0xa2,
+ 0x5d, 0xf7, 0x1a, 0x74, 0xa0, 0x42, 0xdb, 0xdf },
+ { 0x0a, 0x99, 0xe6, 0x53, 0xd7, 0x23, 0xd2, 0x36, 0xaa, 0xf9,
+ 0x8d, 0x74, 0x69, 0x08, 0xd5, 0x63, 0x85, 0x01, 0x56, 0x2e,
+ 0x30, 0x5e, 0x99, 0xf0, 0x13, 0xa3, 0xf1, 0x45, 0x51, 0xd9,
+ 0x10, 0x73, 0x7c, 0x26, 0x4e, 0x6d, 0x48, 0x3e, 0xd8, 0x9a,
+ 0x16, 0xe8, 0xd9, 0x89, 0x24, 0x9e, 0x26, 0xf2, 0xfe, 0xb8,
+ 0xcc, 0xa0, 0xc4, 0x58, 0x45, 0xcf, 0x97, 0xc8, 0xdc, 0x0e,
+ 0xfc, 0x1c, 0xb5, 0xb5, 0xd3, 0x59, 0x47, 0xf5, 0xf3, 0xa8,
+ 0xf7, 0xf0, 0x38, 0xee, 0xc0, 0xcd, 0x28, 0x5d, 0xf2, 0xbf,
+ 0x42, 0xaa, 0x1a, 0xb6, 0x2b, 0x77, 0xb7, 0xa9, 0xe2, 0x6d,
+ 0x90, 0xb1, 0x76, 0x31, 0x91, 0x60, 0x7d, 0x2e, 0xfa, 0xea,
+ 0x79, 0x75, 0x7c, 0xb6, 0xf0, 0x6b, 0xcb, 0xf8, 0xa0, 0xc1,
+ 0xcb, 0x5a, 0xba, 0x60, 0xc5, 0x77, 0xaf, 0xab, 0x5a, 0xeb,
+ 0x11, 0xbb, 0x08, 0xce, 0x89, 0xfc, 0x48, 0xe7 },
+ { 0x3a, 0x95, 0xcb, 0x45, 0x01, 0x0f, 0xcb, 0xc0, 0xb5, 0x95,
+ 0xdb, 0xd1, 0x3e, 0xeb, 0xf7, 0xea, 0x96, 0x50, 0xfc, 0x31,
+ 0x75, 0x32, 0x55, 0x48, 0x9f, 0x76, 0x87, 0x75, 0x33, 0x26,
+ 0x39, 0xe7, 0xd9, 0x73, 0x43, 0xee, 0x83, 0x23, 0xdd, 0xfa,
+ 0xfe, 0x20, 0x21, 0xe3, 0x42, 0x48, 0xe3, 0xd8, 0xc1, 0x26,
+ 0xa9, 0x3a, 0x0d, 0x0e, 0x30, 0x63, 0xcf, 0x74, 0x72, 0x73,
+ 0xf7, 0x84, 0x85, 0x23, 0xc5, 0xcd, 0x9a, 0xbe, 0x29, 0xb7,
+ 0x4d, 0x9a, 0x9a, 0xd3, 0x18, 0x93, 0x8c, 0x17, 0x0a, 0x36,
+ 0xa6, 0xf2, 0xdf, 0x8b, 0x46, 0x65, 0x52, 0xdb, 0xc6, 0x0f,
+ 0xf5, 0x7a, 0xab, 0x79, 0x3a, 0x2d, 0x61, 0x25, 0x4b, 0xe1,
+ 0x13, 0x78, 0xe9, 0x07, 0x22, 0x9f, 0xd2, 0x29, 0x0c, 0x16,
+ 0x81, 0xb5, 0xc1, 0x63, 0x06, 0x7b, 0x9a, 0xa1, 0xa1, 0x60,
+ 0x23, 0x53, 0x6f, 0x46, 0xab, 0xbc, 0x05, 0x59 },
+ { 0x36, 0x6d, 0x22, 0x2e, 0x03, 0x0b, 0x72, 0x45, 0x5d, 0x71,
+ 0x3c, 0x1d, 0xda, 0xd6, 0x72, 0xc3, 0x93, 0x59, 0x7f, 0x66,
+ 0x32, 0x97, 0x84, 0xf1, 0x48, 0x5b, 0xb4, 0x36, 0xcd, 0xba,
+ 0x93, 0xda, 0x01, 0x70, 0x2d, 0xc1, 0x47, 0x44, 0xae, 0xe6,
+ 0xa5, 0xfb, 0x63, 0x9b, 0x41, 0xcc, 0xab, 0xa3, 0x2a, 0x2f,
+ 0xa3, 0xa0, 0x24, 0x53, 0x2a, 0xb3, 0x01, 0x57, 0xca, 0xa4,
+ 0x8c, 0xd0, 0x92, 0xda, 0xf0, 0x07, 0x7c, 0xdb, 0xd2, 0x7e,
+ 0x64, 0xdb, 0x54, 0x5d, 0x09, 0x25, 0x51, 0x86, 0xd2, 0x18,
+ 0x1a, 0x5b, 0xc3, 0xc3, 0xa6, 0x90, 0x2b, 0xda, 0x0c, 0x57,
+ 0x98, 0xab, 0x32, 0xcd, 0x08, 0xd2, 0x79, 0x65, 0xc0, 0xb0,
+ 0x91, 0xca, 0xd8, 0xce, 0x02, 0xa9, 0x2c, 0x77, 0x71, 0x69,
+ 0x43, 0x8a, 0x8d, 0xd1, 0xcb, 0x4b, 0xc1, 0xd5, 0xc4, 0x8f,
+ 0x95, 0x4e, 0x68, 0xcb, 0x39, 0xd7, 0xff, 0x2e },
+ { 0x90, 0x72, 0xba, 0x99, 0x79, 0xde, 0xfd, 0x25, 0x17, 0x3d,
+ 0xcc, 0xd2, 0x06, 0x61, 0xbf, 0xda, 0x44, 0x28, 0x71, 0x53,
+ 0xd3, 0x08, 0x93, 0xfd, 0x4b, 0xb7, 0x6e, 0x73, 0xe5, 0x93,
+ 0x2b, 0x7e, 0x05, 0x5e, 0xa6, 0xdd, 0xad, 0xf1, 0xb3, 0x68,
+ 0x43, 0x40, 0x8d, 0xe1, 0x5f, 0x97, 0x1b, 0x8e, 0x4e, 0x8b,
+ 0x31, 0x45, 0xdd, 0x2f, 0x17, 0x59, 0x98, 0xed, 0x14, 0x99,
+ 0x2b, 0x8a, 0x78, 0xd8, 0x6d, 0xc5, 0xfe, 0xe7, 0x3f, 0x48,
+ 0xca, 0x07, 0x66, 0x92, 0x71, 0x2c, 0x7b, 0x5a, 0xd0, 0x7d,
+ 0xae, 0x14, 0x11, 0x47, 0xd3, 0x2a, 0xcd, 0x21, 0x0b, 0x8e,
+ 0xbf, 0x05, 0xa5, 0x38, 0xbf, 0x49, 0x72, 0x2a, 0x80, 0xa5,
+ 0xcf, 0x11, 0x44, 0x60, 0x7b, 0x53, 0xfa, 0x65, 0x7a, 0x1a,
+ 0x03, 0x10, 0x0f, 0xce, 0x40, 0x1b, 0xa9, 0x0d, 0xa4, 0x4d,
+ 0xd5, 0x0b, 0x48, 0x75, 0x57, 0x3e, 0xa5, 0xb2 },
+ { 0x8d, 0x92, 0xc6, 0xbd, 0x35, 0x54, 0x6c, 0x29, 0x26, 0xac,
+ 0x96, 0x52, 0x43, 0x9d, 0x16, 0x54, 0x7e, 0x8f, 0x23, 0xd9,
+ 0xb6, 0xa8, 0x8f, 0x46, 0x7e, 0x60, 0x8d, 0x97, 0x7d, 0x6c,
+ 0x02, 0xee, 0x4d, 0x81, 0x5a, 0x40, 0x7f, 0x0f, 0x15, 0x3f,
+ 0x6b, 0x19, 0xbe, 0xa9, 0x35, 0xe1, 0x1b, 0xda, 0x33, 0xb2,
+ 0x88, 0x6d, 0x6b, 0x87, 0x1f, 0x8d, 0x56, 0x17, 0x1e, 0xcf,
+ 0xb0, 0xa0, 0xf5, 0x92, 0x6a, 0xe0, 0xe2, 0x2b, 0xfb, 0xdf,
+ 0xa5, 0xba, 0xea, 0x3e, 0x8a, 0xc6, 0x8a, 0xd1, 0x22, 0x42,
+ 0xa6, 0xe4, 0xc9, 0x87, 0x72, 0x9c, 0x09, 0xe3, 0x4e, 0xd0,
+ 0x72, 0xb3, 0x8f, 0x0e, 0xc9, 0xb3, 0x6a, 0x38, 0x28, 0x6f,
+ 0x3f, 0x3d, 0xf1, 0xd5, 0x0b, 0x0e, 0x8b, 0xb1, 0xcd, 0x3a,
+ 0x9c, 0x43, 0xfb, 0xf1, 0x64, 0x9f, 0xc8, 0x31, 0xce, 0xe8,
+ 0x47, 0x4d, 0xe4, 0xdd, 0x96, 0x20, 0xea, 0x39 },
+ { 0x4e, 0x4b, 0xec, 0x17, 0x5c, 0x1a, 0xe5, 0xc0, 0x8d, 0x43,
+ 0xd8, 0x98, 0x8d, 0xd8, 0x27, 0xea, 0xf8, 0x05, 0x39, 0x6c,
+ 0x29, 0x05, 0x3e, 0xf5, 0x30, 0xaa, 0x52, 0xb1, 0xcb, 0xbb,
+ 0x54, 0x70, 0xa8, 0x8f, 0xda, 0xbf, 0x78, 0x88, 0x4c, 0x25,
+ 0x54, 0xbf, 0x9d, 0xe1, 0x53, 0xbd, 0xe6, 0x3d, 0xbe, 0x6a,
+ 0x50, 0x2b, 0x81, 0xf9, 0x0b, 0xdc, 0x97, 0xad, 0xec, 0x2d,
+ 0xf0, 0xa6, 0x21, 0xb0, 0xab, 0xcc, 0x81, 0x5a, 0xfa, 0x57,
+ 0xae, 0x0a, 0x91, 0x6a, 0x77, 0x9c, 0xbd, 0xa0, 0xb9, 0x47,
+ 0x87, 0x4e, 0xe8, 0x40, 0xf9, 0x3f, 0x58, 0x1c, 0x12, 0x45,
+ 0xad, 0xbc, 0x43, 0x5c, 0xfe, 0xe1, 0x9e, 0xce, 0x2e, 0x1f,
+ 0x1c, 0xd4, 0x4b, 0xc3, 0x57, 0xd1, 0xb2, 0x26, 0xde, 0x80,
+ 0x84, 0x99, 0xfb, 0xe3, 0x52, 0x54, 0x3e, 0x0e, 0x42, 0xf8,
+ 0xb3, 0xe0, 0xd7, 0xce, 0xab, 0xeb, 0x0f, 0xf7 },
+ { 0x7a, 0x4a, 0xa3, 0xf5, 0x6f, 0x9d, 0xed, 0x24, 0x72, 0xe6,
+ 0x7d, 0x1a, 0xb4, 0x87, 0x76, 0x77, 0x64, 0x7e, 0x3d, 0x28,
+ 0xec, 0x7e, 0x81, 0xa2, 0x02, 0xb9, 0x4c, 0xb3, 0x32, 0x92,
+ 0x81, 0x3a, 0x44, 0x9c, 0x20, 0xa5, 0x98, 0xf5, 0x08, 0xa8,
+ 0xa9, 0xc8, 0x08, 0x00, 0xec, 0x2c, 0x63, 0xfe, 0x2c, 0x0e,
+ 0x8f, 0x30, 0xff, 0x56, 0xa9, 0xa1, 0xa6, 0xdc, 0xe0, 0x67,
+ 0xb4, 0xe8, 0x33, 0xa5, 0x0b, 0xd4, 0xbc, 0x6b, 0xd4, 0xfd,
+ 0x13, 0x5e, 0x47, 0x70, 0x45, 0x81, 0xb9, 0x0a, 0xf0, 0xb5,
+ 0x8d, 0x1b, 0x95, 0xd0, 0x9e, 0xd7, 0x46, 0xf0, 0x64, 0x4b,
+ 0xba, 0x98, 0x16, 0xe3, 0x51, 0x58, 0xe7, 0x91, 0x5f, 0xd2,
+ 0x84, 0x3f, 0xe7, 0xd8, 0xa6, 0x85, 0x2e, 0xf3, 0xd7, 0x02,
+ 0xa5, 0xdd, 0x45, 0x7c, 0x4a, 0x3f, 0x19, 0xea, 0x9a, 0x94,
+ 0xbf, 0x84, 0x83, 0xa2, 0xfc, 0xc0, 0x96, 0x76 },
+ { 0x60, 0x28, 0x2a, 0x7b, 0xf7, 0xf0, 0xad, 0xe1, 0x0c, 0xbd,
+ 0x7d, 0xc8, 0xc0, 0xa2, 0x69, 0xc5, 0xdc, 0x9d, 0xfa, 0x4f,
+ 0xb4, 0x1a, 0xb5, 0xdf, 0x48, 0xfc, 0xeb, 0xde, 0x9f, 0xd0,
+ 0x9d, 0xf8, 0x15, 0x99, 0x2f, 0xb4, 0x28, 0xd6, 0x9b, 0x12,
+ 0x38, 0xe0, 0xbf, 0x42, 0x1a, 0x19, 0x27, 0x4f, 0xc1, 0xee,
+ 0xb3, 0xf3, 0xa9, 0xd3, 0xfe, 0x55, 0x67, 0xdc, 0xa1, 0x9d,
+ 0xcd, 0xce, 0x38, 0x1e, 0x77, 0x5d, 0xce, 0x9d, 0xb0, 0x51,
+ 0x2e, 0xa6, 0x96, 0xcc, 0x64, 0x0f, 0xcd, 0x3f, 0x4b, 0xb7,
+ 0x74, 0xf8, 0xfe, 0xe0, 0x34, 0xa2, 0xc8, 0x3b, 0x5a, 0xc6,
+ 0x81, 0x32, 0xaf, 0xfa, 0x1f, 0xcf, 0x97, 0x54, 0x4f, 0xc5,
+ 0x9b, 0x3f, 0x9c, 0x54, 0x23, 0xa4, 0x78, 0xe4, 0x39, 0xcf,
+ 0x8d, 0x24, 0xdc, 0x81, 0x2d, 0x4f, 0xb2, 0x42, 0xcb, 0x50,
+ 0x55, 0x9e, 0xf1, 0xba, 0xe2, 0x7a, 0x00, 0x45 },
+ { 0x5f, 0x4a, 0xe9, 0xc7, 0x23, 0xc6, 0xb9, 0x42, 0x3f, 0xd2,
+ 0x86, 0xd9, 0x4a, 0x5f, 0xbe, 0x70, 0xe4, 0x7a, 0x75, 0x39,
+ 0x68, 0xcc, 0x39, 0xed, 0x2d, 0x6a, 0x40, 0x7d, 0xfb, 0xc5,
+ 0xc3, 0x72, 0x55, 0x50, 0xf7, 0xac, 0xd8, 0xc7, 0x3a, 0x43,
+ 0xe9, 0x01, 0x66, 0xd0, 0x0f, 0xa5, 0x16, 0xae, 0x5f, 0xb7,
+ 0x42, 0xf9, 0x19, 0x01, 0x91, 0x38, 0xc3, 0x0b, 0x71, 0x4e,
+ 0x16, 0xfe, 0x46, 0x6a, 0xf1, 0xe8, 0x2f, 0xfe, 0x00, 0x86,
+ 0x9b, 0xcd, 0x38, 0x69, 0x2c, 0xa8, 0x2c, 0xad, 0x14, 0x40,
+ 0x4c, 0x99, 0xf2, 0x58, 0x91, 0xa7, 0xb6, 0x42, 0xc6, 0x3a,
+ 0x34, 0x17, 0xb5, 0xe6, 0xb4, 0x05, 0xf2, 0x1b, 0x69, 0xfb,
+ 0xc7, 0x77, 0x6a, 0x10, 0x67, 0x68, 0x28, 0xf9, 0x4f, 0x1f,
+ 0x65, 0x16, 0x38, 0xa3, 0x22, 0xc8, 0x3c, 0x42, 0x06, 0x1d,
+ 0x7c, 0x07, 0xe5, 0x38, 0xdc, 0xee, 0xa2, 0xe7 },
+ { 0x92, 0xa0, 0x14, 0x23, 0xdc, 0x46, 0xaf, 0xd2, 0x9c, 0xd3,
+ 0xe2, 0x91, 0x40, 0x1a, 0xa5, 0x03, 0x93, 0x9a, 0x7f, 0x26,
+ 0xac, 0xa4, 0xaa, 0x80, 0x2f, 0x64, 0xce, 0x73, 0x51, 0x0e,
+ 0x4d, 0x9c, 0xa2, 0x35, 0x27, 0x35, 0x2f, 0x27, 0x52, 0xaf,
+ 0xf5, 0xb3, 0xb4, 0xc6, 0xc9, 0x01, 0x42, 0x0c, 0x32, 0xee,
+ 0x98, 0xd4, 0x15, 0x66, 0x1c, 0x2d, 0x88, 0xb3, 0x46, 0x49,
+ 0x6b, 0x73, 0x66, 0xa9, 0xbb, 0xca, 0xdb, 0x87, 0x7a, 0x68,
+ 0xfc, 0x0a, 0xa4, 0xbc, 0xa8, 0x6e, 0xa8, 0x65, 0x88, 0x17,
+ 0xb9, 0x8c, 0x47, 0x1e, 0xf9, 0xe5, 0xee, 0x02, 0xc4, 0x15,
+ 0x1b, 0x0a, 0xa3, 0x76, 0x61, 0xb3, 0x25, 0x48, 0x8a, 0x0d,
+ 0x9f, 0x21, 0x95, 0xea, 0x44, 0x9a, 0x01, 0xfb, 0xfd, 0xd4,
+ 0xb0, 0x51, 0x28, 0x6d, 0x45, 0xd0, 0x16, 0xda, 0x19, 0x92,
+ 0xd9, 0x6a, 0x2d, 0xda, 0x53, 0xf4, 0xd5, 0x61 },
+ { 0x0f, 0xc8, 0xfe, 0x1e, 0xaa, 0x88, 0xcb, 0x9b, 0x90, 0x74,
+ 0x87, 0x06, 0x16, 0x1c, 0x51, 0x5b, 0x6f, 0x2c, 0x42, 0x8b,
+ 0x89, 0x60, 0x95, 0x7e, 0xf9, 0x60, 0xb5, 0xb9, 0x94, 0x06,
+ 0xc3, 0xbd, 0x86, 0xdc, 0x2b, 0xa3, 0xe4, 0x88, 0x78, 0x9e,
+ 0x9c, 0xa1, 0x9a, 0x43, 0xd9, 0x9b, 0x08, 0x57, 0x2a, 0x22,
+ 0x62, 0x63, 0x16, 0xa4, 0xc8, 0x7e, 0x04, 0x57, 0x9f, 0x2c,
+ 0xac, 0xb5, 0xe4, 0x6e, 0x9f, 0x62, 0x30, 0xd7, 0x74, 0x24,
+ 0x01, 0x95, 0x82, 0x3f, 0xee, 0x7a, 0x82, 0x56, 0x6a, 0xbd,
+ 0x27, 0x4d, 0xd8, 0x5e, 0x05, 0x8d, 0x90, 0xbd, 0xe8, 0x7f,
+ 0x7d, 0x01, 0x7a, 0x67, 0x56, 0xfb, 0x9a, 0xb7, 0x13, 0xe2,
+ 0x48, 0x14, 0x19, 0x41, 0x96, 0x3e, 0x25, 0xbb, 0x86, 0x48,
+ 0xf1, 0x28, 0xda, 0x8c, 0x90, 0x0f, 0xb7, 0xd5, 0x27, 0xfa,
+ 0xe9, 0xf2, 0x4b, 0xe1, 0x1c, 0x2f, 0x7d, 0xbd },
+ { 0x2d, 0x0b, 0xa8, 0x62, 0xdf, 0xd3, 0x78, 0x9f, 0x3c, 0x95,
+ 0x4d, 0x86, 0xd9, 0x98, 0x92, 0xdd, 0x39, 0x28, 0x5e, 0x51,
+ 0x5d, 0xc6, 0xdc, 0xbe, 0x3a, 0xd2, 0x75, 0x30, 0x5e, 0x88,
+ 0x74, 0xc5, 0xc6, 0xcc, 0xf5, 0xce, 0x70, 0x1a, 0xfb, 0xf3,
+ 0x2b, 0x3f, 0x1d, 0xab, 0xa2, 0xc4, 0xb1, 0x60, 0x95, 0xe8,
+ 0xf4, 0x6e, 0x78, 0xc1, 0x31, 0x8f, 0xe1, 0x50, 0xb6, 0xb4,
+ 0x2b, 0xf3, 0x29, 0x41, 0xdf, 0x36, 0x7c, 0x75, 0x1d, 0x89,
+ 0x83, 0x7e, 0xb1, 0x39, 0x1e, 0x70, 0xc8, 0x60, 0xf3, 0xff,
+ 0xc2, 0x64, 0x86, 0x8e, 0x16, 0x2c, 0xab, 0x31, 0xbd, 0x7e,
+ 0xa7, 0x03, 0x5e, 0x6f, 0x75, 0x29, 0x35, 0x4c, 0x24, 0x10,
+ 0xf8, 0xbe, 0x75, 0xc2, 0x2b, 0xe6, 0x2f, 0x9c, 0xf6, 0x4e,
+ 0x96, 0x35, 0xf3, 0x93, 0xbb, 0x3c, 0xa4, 0x8b, 0x15, 0x59,
+ 0x68, 0xae, 0x1b, 0xed, 0xfe, 0xb9, 0x0f, 0x2d },
+ { 0x96, 0x3c, 0x87, 0x12, 0x4d, 0x41, 0xdb, 0xfc, 0xcc, 0xf6,
+ 0x4c, 0x75, 0x48, 0xa3, 0x76, 0xda, 0x70, 0x53, 0x75, 0xa4,
+ 0x09, 0xb6, 0x23, 0x5b, 0x0d, 0x12, 0x9f, 0x4a, 0x89, 0x49,
+ 0x76, 0x81, 0x26, 0x4c, 0xf1, 0xf9, 0xe2, 0x3c, 0xfb, 0xb7,
+ 0x7b, 0xe7, 0xee, 0xca, 0xa9, 0x33, 0xae, 0x7a, 0x5d, 0x3e,
+ 0x36, 0x7f, 0xb7, 0xf7, 0x0d, 0x81, 0xb9, 0x77, 0x17, 0x55,
+ 0x92, 0xa5, 0xed, 0x54, 0xc1, 0xd2, 0x8c, 0x9f, 0xd5, 0x35,
+ 0x4d, 0x69, 0xee, 0x33, 0x4d, 0xa1, 0xd1, 0x36, 0x67, 0x77,
+ 0x5e, 0xb0, 0x92, 0x5e, 0x9a, 0x81, 0xe5, 0x1e, 0xa9, 0x35,
+ 0x3d, 0xde, 0xa4, 0xee, 0x2f, 0x39, 0xfc, 0xcd, 0x60, 0xd7,
+ 0xfe, 0x6f, 0xc7, 0x06, 0x9b, 0x52, 0x0b, 0xf8, 0xd0, 0xd9,
+ 0x3f, 0xbd, 0xeb, 0x35, 0x4e, 0xae, 0xb7, 0x6a, 0xbb, 0xcc,
+ 0xea, 0xcd, 0x8e, 0xe8, 0xb4, 0x72, 0xe1, 0xaf },
+ { 0x2d, 0x03, 0xeb, 0x3c, 0xff, 0x55, 0xd7, 0xbd, 0x17, 0x51,
+ 0xfb, 0xad, 0xa8, 0xce, 0xc7, 0xef, 0xb2, 0x96, 0xbe, 0x59,
+ 0x5d, 0x57, 0xbe, 0xac, 0x71, 0xda, 0x4f, 0xfa, 0x4e, 0x00,
+ 0xc0, 0xc0, 0x9d, 0x8f, 0xbb, 0x9e, 0x2e, 0xcf, 0x3c, 0x63,
+ 0x3e, 0xb6, 0x63, 0x0a, 0xee, 0xee, 0x42, 0x15, 0xfb, 0x9e,
+ 0x02, 0x84, 0xe3, 0xe6, 0x96, 0xbb, 0x53, 0xe8, 0xbd, 0xf9,
+ 0x43, 0xad, 0x74, 0x9c, 0xff, 0xca, 0x86, 0xaf, 0xf8, 0x48,
+ 0xc1, 0x06, 0xd0, 0xa2, 0x5d, 0x9a, 0xd8, 0x0a, 0x7f, 0x60,
+ 0x85, 0x6a, 0xff, 0x17, 0xbb, 0x51, 0x91, 0x1e, 0x43, 0x4d,
+ 0x76, 0x51, 0x90, 0x29, 0xec, 0x72, 0x0a, 0x7d, 0x19, 0xfd,
+ 0x29, 0x72, 0x0c, 0xea, 0x0e, 0xba, 0xd8, 0x67, 0xf7, 0x7f,
+ 0xe0, 0xe1, 0x9b, 0xdb, 0x01, 0x95, 0x73, 0x3b, 0x12, 0xb5,
+ 0xba, 0xe2, 0x90, 0xcb, 0xde, 0x36, 0xa8, 0x14 },
+ { 0x84, 0x2e, 0x40, 0xc1, 0xc5, 0x4b, 0xac, 0xd9, 0xa3, 0xca,
+ 0x8d, 0x24, 0xa7, 0xcf, 0x61, 0xb7, 0xc2, 0x4f, 0x8a, 0x79,
+ 0x3e, 0xe6, 0xb7, 0xa7, 0xd9, 0x09, 0x32, 0x1b, 0x66, 0x37,
+ 0x82, 0x6b, 0xb9, 0x43, 0x85, 0xa2, 0x63, 0xef, 0xcd, 0x37,
+ 0x2d, 0x44, 0xc7, 0x37, 0xec, 0x2e, 0xe4, 0x11, 0x62, 0x69,
+ 0x84, 0xfe, 0xed, 0x21, 0x9b, 0x6c, 0x88, 0x9e, 0xe7, 0x71,
+ 0xf7, 0x55, 0xba, 0x6e, 0x88, 0x9f, 0x9b, 0xd7, 0x6b, 0xd7,
+ 0x33, 0x5e, 0xf3, 0xc4, 0x46, 0x0f, 0x13, 0xb0, 0xf3, 0xe3,
+ 0x6f, 0x14, 0xef, 0xb5, 0x5e, 0xe8, 0xed, 0x23, 0xc2, 0x82,
+ 0x72, 0xb3, 0x8c, 0xb9, 0x5d, 0x5b, 0x89, 0x1d, 0xf4, 0x4b,
+ 0x3f, 0x71, 0x03, 0x5b, 0x44, 0x2d, 0xf6, 0x04, 0xaa, 0xd9,
+ 0xd9, 0xe0, 0xa8, 0x78, 0xf2, 0x76, 0x0d, 0x14, 0x7e, 0xe2,
+ 0xeb, 0x16, 0x92, 0x5f, 0x04, 0xf2, 0xec, 0x1d },
+ { 0x0e, 0x63, 0x31, 0x9a, 0xca, 0xc9, 0x13, 0x28, 0xa5, 0x96,
+ 0xb7, 0xcb, 0xbc, 0x31, 0xfe, 0x6c, 0x2d, 0x52, 0x66, 0xac,
+ 0x51, 0x28, 0xfc, 0x09, 0x77, 0x73, 0xc2, 0xa5, 0x62, 0x23,
+ 0xd0, 0x93, 0xcc, 0x6a, 0xe2, 0x97, 0x28, 0x5a, 0x40, 0x9f,
+ 0xd5, 0x96, 0x48, 0x14, 0x0d, 0x93, 0x32, 0xd2, 0x8c, 0xaf,
+ 0x6d, 0x9a, 0xcc, 0x87, 0x97, 0xcc, 0xb7, 0xf4, 0xcb, 0x08,
+ 0xe3, 0x07, 0x75, 0x13, 0xac, 0x52, 0x76, 0xc1, 0xdd, 0xe4,
+ 0x55, 0x06, 0xc5, 0x54, 0xec, 0x0a, 0xca, 0x5f, 0xca, 0x2f,
+ 0x82, 0x7f, 0x82, 0xca, 0x1e, 0xfe, 0x42, 0xd0, 0xbd, 0xac,
+ 0x5b, 0xf6, 0x57, 0xb2, 0xe2, 0x80, 0x69, 0x0d, 0xec, 0xb4,
+ 0xc6, 0x69, 0x59, 0x67, 0x16, 0xe6, 0xfe, 0xd1, 0x13, 0x11,
+ 0xe1, 0x77, 0x02, 0x32, 0x8c, 0xca, 0x4f, 0x5b, 0x30, 0xcd,
+ 0x5a, 0x26, 0x8e, 0xd6, 0xa6, 0x61, 0xd8, 0x43 },
+ { 0x88, 0x83, 0x9d, 0xa2, 0x18, 0x72, 0x70, 0x5a, 0x49, 0x39,
+ 0xec, 0xef, 0x28, 0xe1, 0xa7, 0xc2, 0x0b, 0x7a, 0x9d, 0x51,
+ 0xff, 0xa5, 0xa3, 0x5b, 0x27, 0xa5, 0xa2, 0x22, 0xff, 0x83,
+ 0x89, 0xe2, 0xb0, 0x73, 0xbc, 0x04, 0xb3, 0xab, 0xaf, 0x32,
+ 0x90, 0xf3, 0x80, 0x18, 0x9b, 0x4c, 0xe3, 0xb6, 0x93, 0x4d,
+ 0xef, 0xa4, 0x9c, 0x22, 0xa0, 0x06, 0xb4, 0x15, 0x28, 0xb5,
+ 0x9b, 0x7b, 0x42, 0xd5, 0x5b, 0x1a, 0x3d, 0xb5, 0x69, 0xd3,
+ 0xe6, 0xa1, 0xe3, 0x65, 0x9c, 0x29, 0x0b, 0xfc, 0xc7, 0xf5,
+ 0x03, 0x79, 0xa9, 0x6b, 0x3f, 0xcc, 0xc5, 0x2d, 0x3d, 0xfc,
+ 0xf1, 0xb8, 0x52, 0x6c, 0x07, 0x0e, 0x9d, 0x5f, 0xa3, 0x8d,
+ 0xaa, 0x9a, 0xc5, 0x54, 0x82, 0xc6, 0xcf, 0x10, 0xe2, 0x5b,
+ 0x9b, 0x14, 0x86, 0xb6, 0x60, 0xde, 0x28, 0x5e, 0x60, 0x5a,
+ 0xb5, 0xcd, 0x2f, 0xad, 0xf0, 0x36, 0x0a, 0xc2 },
+ { 0x64, 0x12, 0x8c, 0xfe, 0xa1, 0xf5, 0x0c, 0x26, 0xfc, 0x59,
+ 0xcc, 0xa7, 0x1d, 0x2e, 0x21, 0xc9, 0x39, 0xd0, 0xa5, 0x1d,
+ 0x44, 0x15, 0xc3, 0x69, 0xf3, 0x7f, 0xb2, 0xeb, 0xdb, 0x68,
+ 0x1b, 0x90, 0x35, 0x79, 0x1b, 0x90, 0xe9, 0xea, 0xef, 0x52,
+ 0x8f, 0x88, 0xb1, 0xdb, 0xb0, 0x52, 0x19, 0x0b, 0x1f, 0xaa,
+ 0x36, 0xb9, 0x6f, 0xc0, 0x51, 0x80, 0x42, 0x94, 0xf4, 0xf7,
+ 0x35, 0x5b, 0x67, 0x76, 0xc9, 0x34, 0xdb, 0x47, 0x0e, 0x72,
+ 0x73, 0xef, 0x21, 0x7f, 0x27, 0x57, 0x30, 0x00, 0xe9, 0xac,
+ 0xf5, 0xcc, 0xa6, 0x4a, 0xdd, 0x20, 0x38, 0x5a, 0xe7, 0x26,
+ 0x9c, 0x86, 0xfa, 0x2e, 0xe3, 0xca, 0xfe, 0xe5, 0x71, 0xe6,
+ 0x37, 0x3e, 0x3d, 0x13, 0xd4, 0xda, 0xfc, 0x0c, 0x10, 0x5f,
+ 0x9f, 0x21, 0x3a, 0xca, 0xf1, 0x26, 0x58, 0x98, 0x1d, 0x50,
+ 0x56, 0xb6, 0x6c, 0x30, 0x70, 0x1c, 0xe2, 0x9a },
+ { 0x93, 0x63, 0x4a, 0x09, 0xbd, 0xab, 0xcb, 0xda, 0x01, 0x4f,
+ 0x54, 0xda, 0x17, 0x4a, 0x13, 0x2e, 0x32, 0x2c, 0xf0, 0xc2,
+ 0x7c, 0xe9, 0x87, 0x1b, 0x45, 0x99, 0xe9, 0x05, 0xe2, 0x53,
+ 0xe3, 0x7d, 0xd8, 0x65, 0xd0, 0x59, 0x01, 0x6d, 0xae, 0x01,
+ 0x09, 0x10, 0x49, 0xdb, 0x88, 0xb3, 0xa2, 0x06, 0xc6, 0x6b,
+ 0xa6, 0x86, 0x8f, 0x12, 0xcf, 0xd3, 0xdd, 0x4e, 0x27, 0x08,
+ 0x30, 0xc9, 0x28, 0xd1, 0x84, 0x92, 0x28, 0xc0, 0xd5, 0x1a,
+ 0xa4, 0x75, 0x78, 0xdf, 0xf0, 0x0c, 0xd4, 0x48, 0xf3, 0x45,
+ 0x3d, 0x18, 0xf0, 0xed, 0xf3, 0x82, 0x30, 0xf7, 0xf3, 0x9f,
+ 0x00, 0x33, 0xfa, 0xa8, 0xbb, 0xb0, 0x07, 0x5c, 0xa3, 0x46,
+ 0xbc, 0x83, 0xaf, 0x98, 0x41, 0x44, 0x04, 0x41, 0x93, 0xca,
+ 0x7c, 0xec, 0x5c, 0x7e, 0x24, 0x9c, 0xd3, 0x40, 0xf0, 0x59,
+ 0xf0, 0x36, 0x78, 0xa2, 0xe8, 0xf5, 0xb0, 0xb5 },
+ { 0x26, 0x6c, 0xb4, 0x67, 0xbc, 0x06, 0x35, 0x7e, 0x4b, 0x4c,
+ 0x5b, 0xf2, 0x26, 0xde, 0xee, 0xe7, 0xc4, 0x08, 0xc3, 0x2d,
+ 0x9d, 0xcc, 0x22, 0xb2, 0x36, 0x20, 0x77, 0xa3, 0xb4, 0x04,
+ 0x87, 0x63, 0x1e, 0xd6, 0x72, 0xda, 0x4f, 0x87, 0xd7, 0x8e,
+ 0x30, 0x2f, 0x90, 0x9c, 0xd1, 0x39, 0xd6, 0x3b, 0x53, 0x72,
+ 0x77, 0x7b, 0x37, 0x3e, 0x0c, 0xfb, 0x97, 0xf0, 0x00, 0x9a,
+ 0x3f, 0x1c, 0xf6, 0x1e, 0xbb, 0xc1, 0x10, 0x71, 0xb9, 0xde,
+ 0xda, 0x81, 0xe4, 0xcb, 0xa6, 0x01, 0x6f, 0xa9, 0x5e, 0xab,
+ 0x72, 0x95, 0x57, 0x2b, 0x80, 0x38, 0xe6, 0x6d, 0x29, 0x65,
+ 0x5c, 0xf1, 0x2b, 0x5f, 0x46, 0xfd, 0x7e, 0x9b, 0x6b, 0x85,
+ 0xa9, 0x84, 0x7c, 0xfe, 0x91, 0x3a, 0xb8, 0x32, 0x22, 0x38,
+ 0x17, 0x10, 0xc5, 0x7e, 0x18, 0x66, 0xc1, 0xa4, 0xc1, 0x24,
+ 0x62, 0x82, 0x6b, 0x27, 0xa9, 0xa2, 0xe3, 0x04 },
+ { 0x4b, 0x1d, 0x5a, 0x1b, 0x52, 0x45, 0x4e, 0xe1, 0xbc, 0xb0,
+ 0x29, 0xa8, 0x3c, 0x8f, 0x2a, 0xf3, 0x78, 0x2f, 0xd0, 0xd1,
+ 0xf7, 0x47, 0x3a, 0xc1, 0x7e, 0xe7, 0xb5, 0xbc, 0x53, 0x15,
+ 0xb8, 0xd7, 0x09, 0x32, 0xbf, 0xcb, 0xa1, 0xb7, 0xd1, 0x20,
+ 0x15, 0x48, 0x82, 0x8e, 0xc3, 0x6a, 0xb6, 0x11, 0xc1, 0x54,
+ 0xe8, 0x92, 0x63, 0xab, 0x8c, 0x9e, 0x68, 0xb2, 0xf4, 0xeb,
+ 0x9d, 0x5c, 0xf3, 0x64, 0xe3, 0xc3, 0x28, 0x7d, 0x09, 0xf3,
+ 0x51, 0x1d, 0x60, 0x6e, 0x1e, 0xb9, 0x88, 0x70, 0xdc, 0x95,
+ 0x55, 0xca, 0xa8, 0x33, 0xa5, 0x36, 0xbf, 0x78, 0xcf, 0x44,
+ 0xb2, 0xec, 0xf1, 0x99, 0x11, 0xa6, 0x5b, 0x34, 0xae, 0x3e,
+ 0xfa, 0x00, 0x4b, 0x84, 0x14, 0x35, 0x8d, 0xde, 0x2b, 0x9e,
+ 0x65, 0x97, 0x4b, 0x4f, 0xd0, 0x78, 0x3c, 0x1a, 0xa4, 0xdb,
+ 0x6f, 0xaa, 0x41, 0x54, 0xb5, 0x63, 0x63, 0xe8 },
+ { 0x81, 0x86, 0xb9, 0x3f, 0x50, 0x8e, 0x4b, 0x27, 0xe0, 0x74,
+ 0x39, 0xfa, 0xb6, 0x22, 0xd4, 0x2a, 0xc8, 0x31, 0xfd, 0xce,
+ 0x12, 0x0b, 0xf6, 0x19, 0x6f, 0xc0, 0x77, 0x62, 0xbe, 0x6a,
+ 0xbb, 0xd0, 0xbb, 0xf7, 0xee, 0x13, 0x3e, 0xa5, 0xa2, 0xec,
+ 0x0d, 0x4e, 0x56, 0xf1, 0x30, 0xee, 0xa0, 0xe3, 0x10, 0x81,
+ 0x0f, 0x3d, 0x52, 0x07, 0xec, 0x91, 0x7c, 0xc8, 0x00, 0xd4,
+ 0x65, 0x75, 0x7d, 0x4e, 0x32, 0x87, 0x36, 0x1b, 0x0d, 0xf5,
+ 0x11, 0xc8, 0xd7, 0xde, 0x5e, 0x12, 0xfc, 0xa3, 0xda, 0xda,
+ 0xba, 0x31, 0xf6, 0xb5, 0xb1, 0x5e, 0x08, 0x0a, 0x90, 0x12,
+ 0x3a, 0x0a, 0x79, 0x7e, 0x81, 0x07, 0x88, 0xb3, 0xf1, 0xca,
+ 0xac, 0xfa, 0x5a, 0x43, 0x5c, 0x62, 0x15, 0x63, 0x36, 0x0e,
+ 0x39, 0x56, 0x37, 0x35, 0x52, 0x5e, 0x18, 0x8c, 0x09, 0x9d,
+ 0x12, 0xfe, 0x51, 0x74, 0x63, 0xd5, 0x2c, 0x0c },
+ { 0x0b, 0xf9, 0x7e, 0x97, 0xc9, 0xee, 0x2b, 0x2a, 0x47, 0x43,
+ 0xde, 0x57, 0xf3, 0x4a, 0x9b, 0xfa, 0x79, 0xcf, 0xc6, 0xd7,
+ 0x22, 0xc3, 0xab, 0x57, 0x12, 0xbf, 0xff, 0x1a, 0x27, 0xb5,
+ 0x21, 0x4e, 0xb1, 0x39, 0xc0, 0x76, 0x90, 0xbe, 0x35, 0x7e,
+ 0x30, 0x08, 0x6c, 0xf4, 0x43, 0x58, 0x0b, 0x7a, 0xab, 0xa6,
+ 0x58, 0x91, 0x05, 0xd4, 0x11, 0x0a, 0x4b, 0xb8, 0x63, 0xb9,
+ 0xd9, 0x47, 0x7c, 0x91, 0x35, 0x1e, 0x6a, 0x00, 0x9b, 0x7d,
+ 0x9b, 0x1c, 0x7b, 0x5d, 0xc4, 0x44, 0x83, 0x1c, 0x04, 0x97,
+ 0xec, 0xb0, 0x1c, 0x0b, 0xbe, 0xb4, 0xd6, 0x44, 0xed, 0x30,
+ 0xed, 0x65, 0xce, 0x68, 0xb8, 0xfe, 0x50, 0xaa, 0x50, 0x57,
+ 0xa4, 0xfc, 0x3d, 0x82, 0xc1, 0xcf, 0x16, 0x68, 0x1f, 0x5f,
+ 0x5d, 0xda, 0x7e, 0x04, 0x2c, 0x05, 0xbf, 0xaf, 0x7d, 0xb4,
+ 0xc6, 0x19, 0xd1, 0x54, 0x09, 0x31, 0x28, 0x67 },
+ { 0x8f, 0xe5, 0x48, 0x2c, 0x3e, 0x40, 0xaa, 0xbb, 0x3b, 0xd9,
+ 0x1b, 0xb4, 0xfe, 0xaa, 0xc2, 0x3f, 0x57, 0x6a, 0x87, 0x0d,
+ 0x56, 0x76, 0xf1, 0x20, 0xe6, 0xbf, 0xa9, 0xe0, 0x0a, 0x9d,
+ 0x0b, 0xc8, 0x6b, 0x7a, 0xc0, 0xab, 0x9e, 0x69, 0xd9, 0x4e,
+ 0x3d, 0xe3, 0x7a, 0x9a, 0x9f, 0x5e, 0xf4, 0x39, 0xe2, 0x2c,
+ 0x79, 0x76, 0xad, 0x47, 0x35, 0x99, 0xd3, 0xd7, 0x41, 0x6e,
+ 0x1d, 0x2d, 0xc7, 0xdf, 0x9e, 0xb8, 0x1a, 0x0f, 0x32, 0xf1,
+ 0x28, 0x06, 0x18, 0x96, 0xec, 0xda, 0xb3, 0x93, 0x97, 0x30,
+ 0x65, 0xce, 0x25, 0xf1, 0x95, 0xbc, 0x3e, 0x13, 0x98, 0xa6,
+ 0x97, 0xa4, 0x62, 0xfd, 0xcc, 0x09, 0x1a, 0xc6, 0xf6, 0x8b,
+ 0x0d, 0x9a, 0x0d, 0x99, 0x7e, 0x83, 0x61, 0x2b, 0x65, 0xf6,
+ 0x91, 0x8a, 0x54, 0xce, 0x18, 0xea, 0x6c, 0x30, 0x6e, 0x8b,
+ 0x96, 0xec, 0x4e, 0xc8, 0xdd, 0xa1, 0x9e, 0x96 },
+ { 0x39, 0x28, 0xc6, 0x69, 0xbb, 0xc8, 0xbc, 0x3f, 0x4a, 0xeb,
+ 0x62, 0x06, 0xb4, 0x2d, 0x3b, 0xf6, 0x18, 0x9e, 0xd1, 0x8b,
+ 0x6b, 0x4b, 0x5c, 0x8d, 0x95, 0xa9, 0x13, 0xb9, 0xca, 0xd2,
+ 0xde, 0xd6, 0xa6, 0x7c, 0x11, 0x4c, 0x64, 0x27, 0x5d, 0x2c,
+ 0x4c, 0x91, 0x8b, 0xb1, 0x23, 0xda, 0xb5, 0x66, 0xa7, 0xd4,
+ 0x84, 0xbe, 0x0f, 0x64, 0x0a, 0x5f, 0xc5, 0xc0, 0x09, 0xa1,
+ 0x52, 0x19, 0x9f, 0x43, 0x69, 0x67, 0x9f, 0x1e, 0x50, 0xb4,
+ 0xd1, 0x8f, 0xc8, 0x7e, 0xf5, 0x15, 0xb6, 0x4a, 0xe8, 0xb6,
+ 0xdc, 0x62, 0x07, 0x8d, 0xf0, 0x2e, 0xb0, 0xda, 0x99, 0x61,
+ 0xf5, 0xbc, 0xe7, 0x1c, 0x29, 0x4e, 0x80, 0x3d, 0xe0, 0xad,
+ 0x30, 0x8f, 0xb4, 0x1c, 0x5c, 0x6c, 0x8f, 0x3a, 0x25, 0xd0,
+ 0x61, 0x92, 0x4c, 0x3e, 0xb8, 0x03, 0x4f, 0x1d, 0x20, 0x38,
+ 0x85, 0xae, 0x67, 0xc2, 0xce, 0x9a, 0x4d, 0x1e },
+ { 0x6c, 0xcc, 0x88, 0x8f, 0x35, 0x51, 0x34, 0xf6, 0x17, 0x04,
+ 0xd2, 0xe1, 0x91, 0x50, 0xd0, 0xd9, 0x81, 0xc3, 0x5b, 0x3e,
+ 0xf0, 0x71, 0xcd, 0xe4, 0xf0, 0x1d, 0xff, 0x93, 0x73, 0x89,
+ 0x27, 0x54, 0x3b, 0xaa, 0xdc, 0x8b, 0x21, 0xd4, 0x05, 0xd1,
+ 0x1b, 0x14, 0xd9, 0xe6, 0xbe, 0xa1, 0xc1, 0xfd, 0xad, 0xee,
+ 0xfa, 0x98, 0xc2, 0x59, 0xd0, 0xd4, 0x68, 0x1d, 0xf6, 0xdd,
+ 0xa7, 0xc9, 0x30, 0xeb, 0x7f, 0xae, 0x8b, 0xbe, 0x4e, 0x3b,
+ 0x2f, 0x0d, 0x31, 0x67, 0x4a, 0x4f, 0x67, 0xce, 0xe9, 0x84,
+ 0x5a, 0xd8, 0xa5, 0x96, 0x21, 0x21, 0xb7, 0x7b, 0x42, 0x60,
+ 0x42, 0xbc, 0x40, 0x7b, 0x85, 0xc4, 0x90, 0x44, 0x8f, 0xbd,
+ 0xd3, 0x6f, 0x33, 0x1e, 0xf3, 0xaa, 0xc9, 0x4e, 0x7a, 0x91,
+ 0x12, 0xa4, 0x03, 0xf6, 0x2a, 0x44, 0xf2, 0x61, 0x79, 0xa1,
+ 0xde, 0x4b, 0xea, 0x4a, 0xda, 0xcb, 0x4b, 0x64 },
+ { 0x2f, 0x15, 0x19, 0x80, 0xb2, 0x6f, 0xae, 0xf9, 0x6a, 0xfa,
+ 0x63, 0x57, 0xad, 0x4e, 0xd7, 0xbd, 0x03, 0x5f, 0xf1, 0x10,
+ 0xc8, 0xc0, 0xf8, 0x15, 0x8f, 0x79, 0x2b, 0x21, 0x1a, 0xca,
+ 0x3c, 0xe9, 0x53, 0xd5, 0xb8, 0x43, 0x74, 0xb9, 0x13, 0x93,
+ 0xa1, 0x7e, 0x14, 0x84, 0x25, 0x9d, 0x52, 0x54, 0x17, 0xed,
+ 0x0f, 0x5d, 0x39, 0x73, 0xca, 0xcf, 0xa4, 0x84, 0x13, 0x78,
+ 0xfa, 0xb1, 0xe8, 0xbe, 0xcb, 0x8f, 0xd9, 0x8b, 0x9c, 0xbd,
+ 0x35, 0x1a, 0x31, 0x20, 0x24, 0xa9, 0x09, 0xb8, 0xce, 0x1e,
+ 0x0b, 0x8c, 0x1a, 0x82, 0x99, 0xad, 0x8e, 0xb7, 0x68, 0x25,
+ 0xa6, 0xe6, 0x01, 0x4e, 0xdc, 0xfc, 0x12, 0x76, 0xf4, 0xce,
+ 0xba, 0xeb, 0xf3, 0x2f, 0x0d, 0xcd, 0x1e, 0xde, 0xfe, 0xde,
+ 0x67, 0xaa, 0xbc, 0xa3, 0x26, 0x5f, 0xf7, 0x95, 0x9d, 0xdd,
+ 0xf8, 0xd3, 0x6f, 0x0e, 0x7a, 0xd7, 0x50, 0x4c },
+ { 0x35, 0x4b, 0x05, 0xb7, 0x0a, 0xc5, 0x8d, 0x65, 0x6c, 0x80,
+ 0x5c, 0xe8, 0xbe, 0xb5, 0x4a, 0xaa, 0x1c, 0x21, 0x90, 0x85,
+ 0xa8, 0xeb, 0x99, 0x20, 0xf7, 0xbe, 0x03, 0x89, 0x20, 0x5c,
+ 0x4e, 0x92, 0x3a, 0x20, 0x2c, 0x70, 0xfd, 0x22, 0xdf, 0x11,
+ 0xe6, 0x17, 0x32, 0x71, 0xf4, 0xab, 0x67, 0xb3, 0x44, 0xed,
+ 0xf3, 0xf9, 0x13, 0xbe, 0xee, 0xf6, 0x63, 0x8f, 0x6b, 0x74,
+ 0x94, 0x98, 0xfd, 0x7d, 0xc7, 0x1d, 0xb2, 0x90, 0x15, 0xa3,
+ 0x1b, 0xdf, 0x83, 0x81, 0xe3, 0xd8, 0x0a, 0xef, 0x5a, 0x85,
+ 0x03, 0x1d, 0xb9, 0xe7, 0xf3, 0x35, 0x5a, 0x17, 0xba, 0xaa,
+ 0x17, 0x67, 0x9d, 0x88, 0xc6, 0x58, 0x6d, 0x6c, 0xf4, 0xc0,
+ 0xb6, 0xce, 0x47, 0xec, 0x3e, 0x5a, 0x97, 0x92, 0x6c, 0x05,
+ 0xb7, 0x5b, 0x12, 0x1f, 0xbb, 0xc2, 0xbc, 0x03, 0x99, 0x55,
+ 0x0c, 0x86, 0x31, 0xda, 0x29, 0xd2, 0xd4, 0x39 },
+ { 0x48, 0xdc, 0x55, 0xc4, 0xae, 0x35, 0x23, 0xa1, 0xd4, 0x1b,
+ 0xe8, 0x93, 0xcf, 0x09, 0xfa, 0xc2, 0x3e, 0x7d, 0xac, 0xb8,
+ 0x70, 0xac, 0xc7, 0x05, 0x99, 0x38, 0xf9, 0x32, 0xe5, 0x5e,
+ 0xfc, 0xf9, 0x61, 0x96, 0xe2, 0x17, 0xa4, 0x68, 0x1b, 0xe2,
+ 0x84, 0x7a, 0xf9, 0xfc, 0x44, 0x82, 0xf1, 0x3b, 0xf3, 0x1d,
+ 0x33, 0x32, 0xec, 0xa6, 0x86, 0x30, 0xf3, 0x24, 0x1a, 0xb8,
+ 0xa9, 0xf8, 0x1a, 0x18, 0xa3, 0x2f, 0xb5, 0xbc, 0xbb, 0xbc,
+ 0xe7, 0x6f, 0x52, 0x59, 0x1a, 0xc3, 0x2f, 0xf0, 0xa7, 0x2b,
+ 0x00, 0x05, 0x8e, 0x3f, 0x5c, 0x3d, 0x97, 0x1e, 0xb7, 0x13,
+ 0x8a, 0x7f, 0x96, 0x5c, 0x7d, 0x01, 0xa7, 0x3e, 0x8c, 0xe3,
+ 0xa6, 0x6c, 0xae, 0x1a, 0xff, 0xbe, 0x82, 0x4f, 0x3c, 0xdd,
+ 0xcc, 0xfb, 0x01, 0xee, 0xc4, 0x2d, 0x4c, 0xad, 0x50, 0xcd,
+ 0x71, 0x71, 0xe2, 0x36, 0x7a, 0x91, 0x70, 0xe9 },
+ { 0x5f, 0x6a, 0x8e, 0xdd, 0x0b, 0x6d, 0xc0, 0x21, 0x40, 0x5c,
+ 0xe4, 0xc5, 0x66, 0xe3, 0x8c, 0x68, 0x87, 0x25, 0xe2, 0x4b,
+ 0xb9, 0x3b, 0x9c, 0x33, 0xcb, 0x94, 0xcc, 0xff, 0x98, 0x6b,
+ 0x8d, 0x62, 0x19, 0xf2, 0x9d, 0x71, 0x8b, 0x8a, 0xf2, 0xcd,
+ 0x85, 0x1c, 0x9f, 0x4b, 0x1d, 0x0d, 0x7b, 0x3a, 0x5d, 0x67,
+ 0xb9, 0x73, 0xba, 0x15, 0x59, 0x04, 0xcd, 0xeb, 0xa9, 0xf7,
+ 0x71, 0x31, 0x3c, 0x58, 0x18, 0x70, 0x70, 0x75, 0x8a, 0x51,
+ 0xcf, 0x02, 0x15, 0x4e, 0x10, 0x77, 0x8a, 0xf5, 0x88, 0x69,
+ 0x38, 0x2e, 0xb6, 0xe7, 0xa5, 0x12, 0x15, 0x1c, 0x98, 0x2d,
+ 0xef, 0x67, 0x97, 0xd0, 0x0e, 0x38, 0x41, 0x78, 0x06, 0x40,
+ 0x83, 0xc7, 0xd2, 0x45, 0x2f, 0x13, 0x56, 0xaf, 0x25, 0xc9,
+ 0xeb, 0x41, 0xe4, 0x6e, 0xc3, 0x62, 0x68, 0x98, 0x97, 0x0c,
+ 0x8e, 0x62, 0x38, 0x26, 0xa5, 0x09, 0x21, 0x93 },
+ { 0x1c, 0xa6, 0x50, 0x72, 0xca, 0x7f, 0x87, 0xac, 0x2e, 0x12,
+ 0xe0, 0x7a, 0x9e, 0xb8, 0x14, 0xbb, 0x9b, 0x33, 0x48, 0x0d,
+ 0x5a, 0x87, 0x97, 0xd3, 0x15, 0x6c, 0xcb, 0x70, 0x8b, 0xfb,
+ 0x7c, 0xf0, 0x84, 0x0f, 0x04, 0x21, 0xf2, 0x7d, 0xb4, 0x90,
+ 0xcc, 0xe6, 0x56, 0x2b, 0xf4, 0x3c, 0xe0, 0x1e, 0x64, 0x8d,
+ 0xa3, 0x42, 0x0e, 0xa2, 0x43, 0xdb, 0xe4, 0x42, 0x8a, 0xcd,
+ 0xdf, 0x32, 0x57, 0x97, 0x4c, 0xa2, 0xb9, 0xe4, 0x4f, 0xe1,
+ 0xf7, 0x39, 0x53, 0x79, 0x51, 0xb3, 0xb8, 0xa5, 0x97, 0x94,
+ 0x00, 0x5c, 0xfb, 0xba, 0x4e, 0xa4, 0x57, 0xa8, 0x78, 0x04,
+ 0x66, 0x4a, 0x04, 0xaa, 0xb2, 0x6d, 0x4c, 0xd5, 0x8f, 0x16,
+ 0xbc, 0xe3, 0xa4, 0xcf, 0xfb, 0xc1, 0x2d, 0x8c, 0x69, 0x20,
+ 0x10, 0x28, 0x3f, 0x36, 0x97, 0x66, 0x2f, 0x76, 0xa4, 0x07,
+ 0x83, 0x70, 0x4c, 0xa5, 0x8f, 0x9a, 0x86, 0x90 },
+ { 0x46, 0x2c, 0xaf, 0xb6, 0xcb, 0xad, 0x3c, 0xee, 0xac, 0x44,
+ 0xfd, 0x91, 0x35, 0xff, 0xff, 0x64, 0xac, 0xa6, 0x63, 0x99,
+ 0x1f, 0xb3, 0x07, 0xa1, 0x05, 0x5d, 0xec, 0x1c, 0x14, 0xf9,
+ 0xa1, 0x92, 0x9f, 0x7a, 0xff, 0x32, 0x49, 0xfa, 0xca, 0xba,
+ 0xd0, 0xd7, 0x10, 0xc0, 0x68, 0x98, 0x09, 0x85, 0x7f, 0xad,
+ 0x3b, 0xd1, 0xe6, 0x67, 0x54, 0x3c, 0x4d, 0xd2, 0xdb, 0x49,
+ 0x96, 0x46, 0xaa, 0x34, 0xef, 0x8d, 0x44, 0x3e, 0x0d, 0x85,
+ 0x8c, 0x5f, 0x39, 0xb7, 0x52, 0x43, 0x8b, 0xbe, 0x33, 0x91,
+ 0x1d, 0x96, 0xb5, 0x07, 0x89, 0xb7, 0x8d, 0xa8, 0x9b, 0x74,
+ 0xd8, 0xfe, 0x56, 0x47, 0xdd, 0x68, 0x56, 0xed, 0x1e, 0xa4,
+ 0x7d, 0x80, 0x06, 0x8f, 0xc1, 0xc1, 0x53, 0x0e, 0x59, 0xe3,
+ 0x68, 0xb5, 0x66, 0xaf, 0xfd, 0xca, 0x40, 0xa7, 0x46, 0xdb,
+ 0xfb, 0xb3, 0x21, 0xcf, 0x2b, 0x9d, 0x25, 0xa0 },
+ { 0x12, 0x93, 0xc9, 0x8c, 0x6c, 0xd9, 0x36, 0x08, 0x2a, 0x29,
+ 0x15, 0x03, 0xb5, 0x46, 0xea, 0xfd, 0xd2, 0xfb, 0x77, 0x18,
+ 0x3e, 0x8f, 0x9d, 0x13, 0x23, 0x15, 0x5e, 0x22, 0x51, 0x3f,
+ 0x83, 0xc0, 0xaa, 0x78, 0x4f, 0xab, 0x65, 0xf4, 0x85, 0x76,
+ 0x06, 0xfe, 0xe7, 0xfe, 0xd9, 0xba, 0xa6, 0xd3, 0x0f, 0x75,
+ 0xd2, 0x35, 0xa7, 0x32, 0xd1, 0xcc, 0xbc, 0x87, 0x5d, 0x03,
+ 0x0a, 0x2e, 0xbe, 0x41, 0xdf, 0xef, 0xc9, 0x7d, 0xa9, 0xc3,
+ 0x91, 0x7f, 0x4e, 0x7e, 0x8d, 0xfc, 0x25, 0xa9, 0xa1, 0x2b,
+ 0xa1, 0xa2, 0xbe, 0x74, 0x6e, 0xf1, 0x83, 0x31, 0x18, 0x75,
+ 0x39, 0x3d, 0x1c, 0x93, 0xe2, 0x98, 0x15, 0xef, 0x04, 0x3e,
+ 0x72, 0x6b, 0x91, 0x4a, 0xf7, 0x87, 0x9f, 0x59, 0xdd, 0xfa,
+ 0x55, 0xf8, 0x95, 0xf7, 0x35, 0xcc, 0x82, 0xb8, 0x74, 0x04,
+ 0x16, 0x60, 0xa6, 0x47, 0xde, 0x32, 0x37, 0xdd },
+ { 0x53, 0xb7, 0x9a, 0xa1, 0x68, 0xea, 0x94, 0xba, 0x73, 0xe4,
+ 0xb5, 0xf3, 0xe4, 0x6f, 0x8f, 0xb1, 0xed, 0xb2, 0x58, 0x4c,
+ 0x39, 0x46, 0x98, 0x8b, 0xc6, 0x92, 0x9c, 0xd4, 0xfd, 0xfd,
+ 0x61, 0x4f, 0xa0, 0xa4, 0x7f, 0x05, 0x06, 0x4e, 0x71, 0x42,
+ 0x16, 0xe7, 0x9e, 0x41, 0x74, 0xad, 0x91, 0x07, 0xd0, 0x5c,
+ 0x23, 0xc5, 0x49, 0x40, 0xc3, 0xe8, 0x58, 0xcf, 0xb2, 0xfb,
+ 0x1a, 0xe9, 0xd7, 0xc7, 0xbe, 0x1c, 0x0f, 0xb8, 0xa1, 0xbd,
+ 0x18, 0x9e, 0xca, 0x83, 0xcb, 0x86, 0xe7, 0x7b, 0x11, 0x1a,
+ 0xb0, 0xb0, 0x28, 0x9c, 0x8c, 0x87, 0x53, 0x0d, 0x49, 0x5f,
+ 0x6a, 0xbf, 0x33, 0xb3, 0x75, 0x22, 0x82, 0x38, 0xc7, 0x08,
+ 0x87, 0xe7, 0x71, 0xc1, 0xb7, 0xd7, 0xc7, 0xdb, 0x4a, 0x36,
+ 0xb7, 0x11, 0xa6, 0xab, 0x40, 0x3d, 0x96, 0xea, 0xfa, 0xc7,
+ 0x72, 0x78, 0x12, 0x51, 0x49, 0xd5, 0x3b, 0x77 },
+ { 0x82, 0x90, 0xd6, 0xd1, 0x56, 0xc2, 0xe8, 0x33, 0x40, 0xa6,
+ 0xf7, 0xd5, 0xf3, 0x87, 0x2c, 0x9d, 0x15, 0x0f, 0xb4, 0xa9,
+ 0x58, 0x40, 0x11, 0x04, 0xc8, 0x9d, 0xc0, 0x1b, 0x32, 0x81,
+ 0x51, 0xe1, 0xe5, 0xef, 0x49, 0x97, 0xc8, 0x3a, 0xf2, 0xa8,
+ 0x04, 0x09, 0x99, 0x03, 0xc9, 0xd5, 0xda, 0x0f, 0xb9, 0x28,
+ 0x7f, 0x58, 0x53, 0x46, 0x61, 0x1d, 0x64, 0x00, 0xbc, 0x54,
+ 0x23, 0x45, 0x96, 0xc4, 0x0d, 0x53, 0x9d, 0x8d, 0x47, 0x39,
+ 0x7c, 0x05, 0x23, 0x11, 0x98, 0x69, 0x29, 0xfe, 0x89, 0xa2,
+ 0x64, 0x96, 0x8e, 0xe6, 0x51, 0x2c, 0x67, 0x38, 0xfe, 0xd5,
+ 0xab, 0xce, 0x7b, 0x4e, 0xc0, 0x14, 0x02, 0x2e, 0xaf, 0x3d,
+ 0xf1, 0x9e, 0xfa, 0xfe, 0xef, 0x1e, 0x4b, 0x30, 0xa9, 0xdd,
+ 0x93, 0x9a, 0xd3, 0xa5, 0xbb, 0xa0, 0x67, 0x82, 0x17, 0x28,
+ 0x21, 0x6f, 0xaf, 0xce, 0x44, 0xbb, 0xb6, 0xa1 },
+ { 0x50, 0x6e, 0xf1, 0xab, 0x30, 0x4f, 0xab, 0xb0, 0x6f, 0xa1,
+ 0xd9, 0x69, 0xee, 0x95, 0x2e, 0x14, 0x45, 0x9f, 0x29, 0x7b,
+ 0xa0, 0xaa, 0x98, 0x4e, 0x00, 0xf3, 0x32, 0xe1, 0xec, 0x47,
+ 0xb3, 0xcf, 0xfd, 0x22, 0x3e, 0x26, 0xf0, 0x6a, 0x2a, 0x08,
+ 0x51, 0xcc, 0x6e, 0xf9, 0xb3, 0x3f, 0xa0, 0xe1, 0x1b, 0xea,
+ 0xd0, 0x2c, 0xa6, 0x75, 0x23, 0x5a, 0x6e, 0x6b, 0x55, 0xe9,
+ 0xdb, 0x32, 0x16, 0x60, 0x23, 0x80, 0xed, 0x5c, 0xed, 0x96,
+ 0x78, 0x11, 0xcc, 0x20, 0x8d, 0xe6, 0x33, 0xaa, 0xfc, 0xa5,
+ 0xa2, 0x71, 0x4c, 0xa6, 0x0b, 0xca, 0xdb, 0x5f, 0xe6, 0x2a,
+ 0xe5, 0x2d, 0x2d, 0x67, 0x84, 0xa9, 0xb4, 0x25, 0x57, 0xfe,
+ 0x0d, 0xc7, 0xb8, 0x09, 0xd4, 0x23, 0x59, 0xa4, 0xd7, 0x89,
+ 0x00, 0x7e, 0xda, 0x13, 0x4a, 0x39, 0x69, 0xec, 0x57, 0xfa,
+ 0xf8, 0x46, 0x37, 0xc6, 0xd8, 0x54, 0x69, 0x46 },
+ { 0x41, 0x5b, 0x7d, 0xbf, 0x15, 0x20, 0x03, 0x44, 0xda, 0xaf,
+ 0x3f, 0xdb, 0x4d, 0x85, 0xc6, 0x78, 0x6c, 0xcd, 0x2f, 0xbf,
+ 0xf7, 0x1a, 0x70, 0x6e, 0x14, 0x04, 0xcc, 0xf8, 0xb9, 0x8f,
+ 0xcb, 0xc7, 0xfa, 0xbe, 0x77, 0x43, 0xfa, 0x8f, 0xeb, 0x1f,
+ 0xe1, 0x4a, 0x45, 0x6f, 0x8e, 0xed, 0x67, 0x65, 0x6e, 0xec,
+ 0x74, 0xd2, 0x37, 0x9d, 0x92, 0xd1, 0xdf, 0xea, 0x34, 0x23,
+ 0xd4, 0xdc, 0xbc, 0x3c, 0xdd, 0x35, 0x4c, 0xac, 0xbd, 0xc8,
+ 0x9a, 0x16, 0xa2, 0x8d, 0x63, 0x3d, 0xdf, 0x73, 0xad, 0x9c,
+ 0x36, 0xa6, 0xaf, 0x39, 0xe3, 0x07, 0x1b, 0x58, 0xf5, 0x09,
+ 0x0a, 0x7e, 0xa7, 0x30, 0x75, 0xaa, 0xa2, 0xda, 0xf1, 0xa5,
+ 0x9d, 0xd1, 0xc3, 0xd5, 0x66, 0xac, 0xeb, 0x3f, 0x9d, 0xeb,
+ 0x27, 0xce, 0x71, 0x30, 0xb9, 0x6f, 0xea, 0x9f, 0xa9, 0x84,
+ 0x11, 0xb4, 0xeb, 0x27, 0x35, 0xbf, 0xf1, 0x63 },
+ { 0x1e, 0xc3, 0x14, 0xf1, 0xaf, 0x58, 0x87, 0x9d, 0x52, 0x5d,
+ 0xc9, 0xbd, 0xec, 0x83, 0x1d, 0x59, 0xfc, 0xe0, 0xfa, 0xfc,
+ 0xc1, 0x75, 0xd4, 0x3f, 0x00, 0x69, 0x65, 0xed, 0xb4, 0x12,
+ 0x2e, 0x05, 0x35, 0x22, 0xce, 0xf0, 0xa2, 0xb5, 0x51, 0x1c,
+ 0x76, 0x9a, 0x2e, 0xf9, 0x85, 0xf0, 0x68, 0xaa, 0x01, 0xdc,
+ 0x4c, 0x3f, 0xe6, 0x93, 0x65, 0x08, 0xf9, 0x31, 0x8c, 0x91,
+ 0x97, 0xf0, 0x0f, 0x11, 0x45, 0x49, 0x97, 0x51, 0x86, 0x32,
+ 0x0a, 0x01, 0x0c, 0xda, 0x36, 0xd9, 0x6e, 0x0e, 0x54, 0xc2,
+ 0xfc, 0x6a, 0xc6, 0xc6, 0x0f, 0xeb, 0x9f, 0x3b, 0x71, 0x2f,
+ 0xa1, 0x3c, 0xe9, 0xe5, 0xa2, 0xb8, 0x4b, 0xc7, 0x09, 0x5d,
+ 0x93, 0xc8, 0xf2, 0x90, 0xfd, 0x67, 0xd2, 0x89, 0xf0, 0x3a,
+ 0x4c, 0x32, 0x06, 0x8a, 0x3d, 0x68, 0xcb, 0x80, 0x32, 0x72,
+ 0x97, 0x01, 0x05, 0x86, 0x7d, 0x83, 0x77, 0xa7 },
+ { 0x17, 0xe9, 0x1d, 0x12, 0x7f, 0xff, 0x57, 0x88, 0xad, 0x5c,
+ 0xc0, 0x8f, 0x2d, 0xc1, 0x05, 0xde, 0x71, 0x93, 0x6c, 0xb4,
+ 0x52, 0xab, 0xfa, 0x6b, 0x76, 0x51, 0x35, 0xd2, 0x3d, 0xe5,
+ 0xa6, 0x64, 0xbb, 0x32, 0xf1, 0x7c, 0x96, 0x93, 0x9c, 0x82,
+ 0xe0, 0xc8, 0xb6, 0xf7, 0xf5, 0x87, 0x5a, 0xec, 0xa9, 0x31,
+ 0xb9, 0x9d, 0x77, 0x46, 0xe0, 0xc7, 0xd3, 0xbb, 0x0a, 0x97,
+ 0x26, 0xec, 0xcf, 0xa0, 0xf0, 0x01, 0xc4, 0x6e, 0xdd, 0x2f,
+ 0x9e, 0x6f, 0x01, 0x8b, 0x1c, 0x63, 0xae, 0x4b, 0x9b, 0xc6,
+ 0x34, 0x13, 0x02, 0xf9, 0xf7, 0xde, 0x17, 0x11, 0x50, 0x77,
+ 0x33, 0x20, 0xb5, 0x42, 0xf8, 0xdf, 0xcd, 0xe4, 0xa3, 0x8f,
+ 0x63, 0x7e, 0xc2, 0xc5, 0x39, 0x2b, 0x10, 0xfc, 0xe5, 0x34,
+ 0x68, 0x87, 0xaa, 0x7e, 0x14, 0xda, 0x45, 0x7e, 0x3f, 0x74,
+ 0x06, 0x63, 0xfe, 0xef, 0x2c, 0x83, 0x10, 0xc2 },
+ { 0x11, 0x8f, 0x3b, 0x4b, 0x3d, 0xdd, 0x0c, 0x01, 0xdf, 0x24,
+ 0x22, 0x82, 0xaf, 0xc4, 0xa0, 0xd5, 0x16, 0x29, 0xf7, 0xc2,
+ 0x63, 0xf7, 0xb9, 0x7e, 0xf3, 0x01, 0xa3, 0x8f, 0xb1, 0x8a,
+ 0xe1, 0xf9, 0xca, 0x7c, 0x98, 0xed, 0x57, 0x25, 0x71, 0xdf,
+ 0x6e, 0x65, 0x3e, 0xa4, 0x1d, 0xeb, 0x3e, 0x28, 0x99, 0x58,
+ 0x4a, 0xeb, 0x91, 0xd4, 0xa3, 0xb6, 0x0d, 0x76, 0x59, 0x57,
+ 0xb5, 0x99, 0x73, 0x2d, 0x35, 0x49, 0x97, 0xe4, 0x77, 0x96,
+ 0x3e, 0x0e, 0xa7, 0xbd, 0x46, 0x92, 0x8c, 0x36, 0x5a, 0xec,
+ 0x54, 0x50, 0x9e, 0x65, 0xd1, 0x2a, 0x19, 0xee, 0x39, 0x52,
+ 0x49, 0xa3, 0xd2, 0x89, 0xe9, 0xc7, 0x3e, 0xa6, 0x62, 0x27,
+ 0xce, 0x9d, 0x6b, 0x31, 0xc8, 0xab, 0x4b, 0x52, 0x00, 0x86,
+ 0x78, 0x4b, 0xc6, 0x44, 0xd4, 0xfd, 0x19, 0xc7, 0x76, 0xd4,
+ 0xbe, 0x92, 0xce, 0xd3, 0xb7, 0xe0, 0x51, 0xca },
+ { 0x01, 0xd0, 0xa6, 0x7c, 0x8d, 0x03, 0xe7, 0x27, 0x3b, 0x9b,
+ 0x53, 0x6a, 0x44, 0xf1, 0x70, 0x24, 0x22, 0xce, 0x8a, 0x79,
+ 0x44, 0xf5, 0x93, 0xc2, 0x21, 0xd2, 0xb6, 0x31, 0x21, 0xb6,
+ 0x17, 0x10, 0x1d, 0xbd, 0xbd, 0x1a, 0xc2, 0xdd, 0x61, 0x7f,
+ 0x87, 0x8e, 0xcc, 0x0d, 0x00, 0x71, 0x5b, 0xa1, 0x15, 0x61,
+ 0x8d, 0x0b, 0x1b, 0xdf, 0xe5, 0x2f, 0x5b, 0xc1, 0x8b, 0x4f,
+ 0xdf, 0x75, 0x86, 0x95, 0x73, 0x5e, 0xb6, 0x86, 0xe7, 0x7a,
+ 0x4c, 0x05, 0xa3, 0xe1, 0x78, 0x34, 0x5b, 0x08, 0x46, 0xe5,
+ 0xc2, 0x44, 0xa6, 0x09, 0x5d, 0xd6, 0x14, 0x7a, 0x83, 0x63,
+ 0x7f, 0xfb, 0x3e, 0xcc, 0x1d, 0xba, 0xc0, 0xbe, 0x87, 0x86,
+ 0x7e, 0x60, 0xd9, 0x8b, 0x16, 0xff, 0x49, 0x60, 0x4c, 0xf7,
+ 0x6d, 0x86, 0x1a, 0xef, 0x84, 0xda, 0x8c, 0x58, 0xd1, 0x75,
+ 0x74, 0xa0, 0xa0, 0xa8, 0x7a, 0xd4, 0x76, 0x2b },
+ { 0x1b, 0x62, 0x5b, 0x06, 0x7d, 0xa6, 0x32, 0x0f, 0xc9, 0xad,
+ 0xba, 0x24, 0x99, 0x7c, 0x08, 0xe6, 0xdd, 0x52, 0x7b, 0x43,
+ 0xc5, 0x6b, 0xb0, 0x44, 0xca, 0xdd, 0x2d, 0xfa, 0x48, 0x6e,
+ 0x2f, 0x84, 0x5a, 0xd8, 0xb5, 0x72, 0xc9, 0x50, 0xd5, 0xd4,
+ 0x7f, 0x47, 0xd4, 0x56, 0xb4, 0xed, 0x85, 0x69, 0x52, 0x36,
+ 0x4b, 0xa1, 0xfa, 0xbd, 0x59, 0x52, 0xcd, 0x57, 0x2d, 0xfd,
+ 0x2a, 0xf0, 0x3b, 0x37, 0x59, 0x6c, 0xce, 0xb5, 0xd2, 0xe8,
+ 0x65, 0x0a, 0x03, 0xd5, 0x45, 0x21, 0x11, 0xe6, 0x8d, 0xa6,
+ 0x7b, 0x67, 0xec, 0xdb, 0xe7, 0x6c, 0x0d, 0x63, 0x74, 0xa6,
+ 0x9b, 0xdd, 0x4c, 0xb6, 0x63, 0xe3, 0x71, 0x35, 0xe8, 0x1d,
+ 0xd8, 0x3c, 0x7a, 0x45, 0x01, 0x9b, 0x5d, 0x16, 0xa4, 0x2c,
+ 0x4a, 0x18, 0xe9, 0x47, 0x79, 0x90, 0xfb, 0x88, 0xc2, 0xae,
+ 0x7b, 0x96, 0x42, 0x36, 0x1e, 0x46, 0x53, 0x3c },
+ { 0x33, 0x3e, 0xca, 0x96, 0x19, 0xfc, 0x94, 0x8d, 0xbd, 0xf1,
+ 0x43, 0x28, 0x84, 0x00, 0x73, 0x6e, 0x15, 0x39, 0x79, 0x21,
+ 0xa7, 0x07, 0x66, 0x39, 0x13, 0xf5, 0xca, 0x6f, 0xbf, 0x06,
+ 0x97, 0x68, 0x32, 0x1f, 0xaa, 0xc2, 0x98, 0x26, 0x65, 0x6a,
+ 0xc4, 0xca, 0x56, 0x7c, 0x36, 0x0c, 0xb3, 0x65, 0xf6, 0x68,
+ 0x20, 0x65, 0x3f, 0x7d, 0xf0, 0xc2, 0x6d, 0x6e, 0x32, 0x58,
+ 0x24, 0x33, 0xda, 0x34, 0xdb, 0x1f, 0x80, 0xc6, 0x34, 0xd8,
+ 0x52, 0xd7, 0x87, 0xdc, 0xb5, 0x34, 0x2b, 0x41, 0xc5, 0xdd,
+ 0x6b, 0x24, 0x5e, 0x5c, 0x1f, 0x49, 0x09, 0x8b, 0x2b, 0x97,
+ 0x1c, 0xba, 0x87, 0x15, 0x6b, 0xc9, 0xf3, 0x3c, 0x43, 0x4f,
+ 0xbb, 0xa9, 0x75, 0x8b, 0xbf, 0x44, 0x43, 0x88, 0xfe, 0x88,
+ 0x38, 0xb5, 0xc0, 0x1b, 0x2f, 0x01, 0xaf, 0x6f, 0xeb, 0xeb,
+ 0x44, 0xdf, 0xaa, 0x7b, 0x4f, 0xd8, 0x44, 0x6d },
+ { 0x72, 0xfc, 0x21, 0x10, 0x87, 0x28, 0xd1, 0x35, 0xae, 0x9d,
+ 0x9c, 0x07, 0x4c, 0xcf, 0x07, 0x46, 0x4d, 0x25, 0xc7, 0x42,
+ 0xf2, 0xcd, 0x13, 0x4f, 0x76, 0x50, 0x82, 0xa5, 0x37, 0xe7,
+ 0xb1, 0x5d, 0x55, 0x7b, 0x32, 0x2a, 0x65, 0xcd, 0x44, 0x9d,
+ 0x98, 0x7d, 0xa7, 0x4a, 0xe5, 0x4b, 0x64, 0xa7, 0xf3, 0x5e,
+ 0x8c, 0xf1, 0x33, 0x93, 0x74, 0x3e, 0x90, 0xc1, 0x6e, 0xeb,
+ 0xcb, 0x25, 0xb9, 0x99, 0x5a, 0x17, 0xf8, 0xe5, 0x1d, 0x61,
+ 0x6e, 0x91, 0xd7, 0x24, 0x08, 0xdc, 0x52, 0x35, 0x96, 0x61,
+ 0x5d, 0xb3, 0x56, 0x5a, 0x7f, 0x5c, 0x01, 0xf0, 0x2b, 0x3a,
+ 0x13, 0xa4, 0x13, 0xfb, 0x3b, 0x5b, 0xaa, 0xd3, 0x62, 0x36,
+ 0x54, 0x70, 0x3f, 0xe7, 0x62, 0x3c, 0x7a, 0x4f, 0xbc, 0xfc,
+ 0xe9, 0x48, 0x38, 0xc2, 0x51, 0x8f, 0xd4, 0x1d, 0xbb, 0xca,
+ 0x23, 0x33, 0x79, 0x48, 0xac, 0x77, 0x5d, 0x81 },
+ { 0x48, 0x09, 0x46, 0xf8, 0xb1, 0x1e, 0xd9, 0x2d, 0x23, 0x8e,
+ 0xf1, 0x7c, 0x88, 0x40, 0xa6, 0xc6, 0xe1, 0xa2, 0x73, 0x8e,
+ 0xa1, 0x7e, 0x35, 0xa4, 0xe5, 0x73, 0xf6, 0x48, 0x9d, 0xef,
+ 0xf9, 0xa0, 0x03, 0x80, 0x3d, 0x84, 0x56, 0x17, 0x70, 0x40,
+ 0x1e, 0xe4, 0x8d, 0xe3, 0x2f, 0x7b, 0x16, 0x5b, 0x76, 0x0f,
+ 0x8d, 0x28, 0x5c, 0x2f, 0xfc, 0x3c, 0x22, 0x8a, 0x39, 0x1b,
+ 0x5d, 0x33, 0x6d, 0x51, 0xfb, 0xbd, 0xcf, 0x0c, 0x7d, 0x3d,
+ 0xe6, 0x66, 0xeb, 0x9a, 0xde, 0x06, 0x9a, 0x3d, 0xf8, 0x5e,
+ 0x4a, 0x1f, 0xee, 0x78, 0xbc, 0xe8, 0x20, 0x62, 0x91, 0xc8,
+ 0xcc, 0xa9, 0x55, 0xa0, 0x60, 0x81, 0x4a, 0x9e, 0xa6, 0xfb,
+ 0xe5, 0x50, 0xc8, 0xee, 0xd7, 0x7d, 0x58, 0x67, 0x55, 0xf3,
+ 0x59, 0x09, 0xd8, 0x3f, 0x95, 0xcf, 0x45, 0x80, 0x55, 0xff,
+ 0xa9, 0x06, 0xb2, 0x03, 0xf9, 0x60, 0x04, 0xc8 },
+ { 0x8d, 0xab, 0x61, 0xfd, 0xc7, 0x38, 0x69, 0x02, 0x16, 0xe8,
+ 0xe8, 0xae, 0xcf, 0x68, 0xaf, 0xc7, 0xf8, 0x6f, 0x2b, 0xe6,
+ 0xc1, 0xf8, 0x53, 0x9f, 0xc0, 0x1c, 0x2e, 0xb2, 0x46, 0x46,
+ 0x4d, 0x9e, 0xa1, 0xae, 0x66, 0x6b, 0x4b, 0xa8, 0x46, 0xe4,
+ 0xcb, 0x3b, 0x43, 0x61, 0xe4, 0xbb, 0xd0, 0x07, 0x00, 0x89,
+ 0xc0, 0x6e, 0x7d, 0x06, 0xe6, 0x84, 0xe2, 0x77, 0x5e, 0xb6,
+ 0x09, 0x92, 0xf7, 0xd0, 0x3b, 0x72, 0xb0, 0x4d, 0x6c, 0x2b,
+ 0x7d, 0xd4, 0xc8, 0x86, 0x9a, 0xba, 0xe2, 0x0f, 0xd6, 0x24,
+ 0x84, 0x97, 0x50, 0x96, 0x2c, 0xaa, 0xf8, 0x92, 0xa1, 0xa9,
+ 0x90, 0x24, 0xc6, 0x30, 0xb8, 0xc0, 0x48, 0xa4, 0x88, 0x99,
+ 0xab, 0x18, 0xd6, 0xf4, 0x0e, 0x2f, 0x67, 0x86, 0x62, 0x98,
+ 0x58, 0x7a, 0x19, 0xe6, 0x5c, 0x5e, 0x53, 0xeb, 0x36, 0x95,
+ 0x84, 0xc7, 0x47, 0xa8, 0xfd, 0x71, 0xf1, 0x19 },
+ { 0x6f, 0x77, 0xe6, 0x2d, 0xf9, 0x9b, 0x29, 0xe7, 0xe0, 0x3c,
+ 0xa8, 0x79, 0x11, 0x8f, 0x69, 0x0c, 0x9d, 0xef, 0x7a, 0xd1,
+ 0x67, 0xb9, 0x7e, 0xe1, 0x3e, 0xb2, 0x1b, 0x14, 0xcb, 0xd7,
+ 0xce, 0xf1, 0x55, 0xbe, 0x8a, 0x15, 0x2c, 0xaf, 0x08, 0x0e,
+ 0x5e, 0xce, 0x77, 0xab, 0xb8, 0x16, 0x9f, 0xed, 0x86, 0x94,
+ 0x22, 0x9f, 0x31, 0xdc, 0xc9, 0x57, 0xa1, 0x04, 0x44, 0xeb,
+ 0xa5, 0x90, 0x70, 0x0d, 0x80, 0x27, 0x14, 0xc1, 0x9e, 0xc5,
+ 0x15, 0x02, 0x87, 0x7f, 0x8b, 0xcf, 0x3f, 0x06, 0xfd, 0xc2,
+ 0x1d, 0xe7, 0x6a, 0xed, 0x91, 0x1f, 0x32, 0xe6, 0xd3, 0xd2,
+ 0x39, 0xbb, 0x34, 0x86, 0x54, 0x02, 0x35, 0xb2, 0xba, 0x2b,
+ 0x08, 0xc4, 0x62, 0x1a, 0x2d, 0x88, 0xb5, 0x20, 0x34, 0xd4,
+ 0x78, 0xb4, 0xac, 0xd4, 0x29, 0x7e, 0xff, 0x4f, 0x9b, 0xa2,
+ 0x42, 0xa5, 0xc9, 0x03, 0xd5, 0x4d, 0x1d, 0x45 },
+ { 0x63, 0x81, 0x9c, 0x91, 0xc3, 0xd2, 0xcf, 0x80, 0x79, 0x9d,
+ 0x78, 0x86, 0x81, 0x84, 0xf0, 0xeb, 0x23, 0x44, 0xe0, 0x0f,
+ 0x68, 0xbe, 0xd1, 0x02, 0xee, 0x6d, 0x75, 0x78, 0xc1, 0xcf,
+ 0x55, 0x80, 0x86, 0x13, 0x60, 0x73, 0x2e, 0x5a, 0x8b, 0xe6,
+ 0xae, 0x5e, 0x2e, 0x76, 0xd6, 0x69, 0x84, 0x0a, 0x31, 0x4d,
+ 0x5d, 0x57, 0x77, 0x3b, 0x7b, 0x3a, 0x91, 0xe0, 0xa2, 0xef,
+ 0x06, 0xc0, 0xcc, 0x42, 0x99, 0xaa, 0xfa, 0xbf, 0xf8, 0x5c,
+ 0x3f, 0xbf, 0x11, 0xaa, 0x01, 0x2f, 0xff, 0x3b, 0xf3, 0xb5,
+ 0x97, 0x92, 0xa8, 0xfd, 0x6f, 0x38, 0xea, 0xc7, 0x22, 0xeb,
+ 0x71, 0x13, 0xa8, 0x13, 0x35, 0x9f, 0x34, 0x65, 0xb4, 0x66,
+ 0x4b, 0x71, 0xb0, 0x2f, 0x17, 0x55, 0xe0, 0x35, 0x73, 0x54,
+ 0x1c, 0xd1, 0x17, 0x7b, 0xa4, 0x53, 0x64, 0x01, 0xaa, 0xd6,
+ 0xa2, 0x71, 0xbd, 0xed, 0xe4, 0x0b, 0xbf, 0x59 },
+ { 0x67, 0xd4, 0x8d, 0x12, 0x82, 0x65, 0xd7, 0xee, 0xc8, 0x0a,
+ 0xfe, 0xec, 0x55, 0xe4, 0x9b, 0x47, 0xe4, 0x3a, 0x0b, 0xe7,
+ 0x0a, 0x2f, 0x8c, 0xab, 0xc0, 0xd0, 0x31, 0x9a, 0x50, 0x4b,
+ 0x6b, 0xc1, 0xe0, 0xfc, 0x16, 0xd3, 0x4e, 0xbd, 0x45, 0x3e,
+ 0xe1, 0x31, 0xcc, 0x9a, 0xbd, 0xa6, 0x12, 0x5a, 0x10, 0xb2,
+ 0xcf, 0xe7, 0x97, 0x6a, 0x84, 0x4b, 0x1f, 0xf6, 0x0c, 0x51,
+ 0xa0, 0xd3, 0xd8, 0x1a, 0xc5, 0xb3, 0x37, 0x6f, 0x17, 0x1d,
+ 0x12, 0x04, 0x5a, 0xab, 0xf3, 0x91, 0xfa, 0xde, 0x65, 0x00,
+ 0xeb, 0xf5, 0x75, 0x89, 0x2a, 0xea, 0x4f, 0xbf, 0xf9, 0x66,
+ 0x64, 0xee, 0x1b, 0xf9, 0x6b, 0x91, 0xcb, 0x2a, 0xc0, 0x7c,
+ 0xe4, 0xc4, 0x7b, 0x70, 0x3d, 0x07, 0xf5, 0xf0, 0x90, 0x70,
+ 0x38, 0xa7, 0x9e, 0xc3, 0xa1, 0xfc, 0xeb, 0x12, 0x67, 0xea,
+ 0xca, 0x53, 0x92, 0xe1, 0x78, 0x84, 0xb0, 0x73 },
+ { 0x27, 0x95, 0x0e, 0x38, 0xe8, 0x38, 0x4d, 0xc7, 0xa3, 0xd7,
+ 0xeb, 0xc3, 0x1f, 0x0e, 0x43, 0xf5, 0x2c, 0xf1, 0x13, 0xa9,
+ 0x28, 0xb0, 0x1d, 0xf5, 0xd4, 0x90, 0x0d, 0x0f, 0x10, 0xd1,
+ 0xc1, 0x84, 0x3e, 0xfc, 0xaa, 0x50, 0xab, 0xf2, 0x94, 0x01,
+ 0xfe, 0x8b, 0xb1, 0x20, 0x5e, 0xe6, 0x05, 0x96, 0xfd, 0xd5,
+ 0x6b, 0x1b, 0x4d, 0xc9, 0x27, 0xcd, 0x95, 0xf6, 0x2c, 0x85,
+ 0xc5, 0xb6, 0x49, 0xd4, 0x84, 0x22, 0x9d, 0xf4, 0x75, 0x61,
+ 0xa0, 0x10, 0x47, 0x2d, 0xdc, 0x3d, 0x64, 0xa2, 0xf9, 0xa8,
+ 0xde, 0xe7, 0xca, 0x2b, 0x75, 0xba, 0x8c, 0x3d, 0x89, 0xa2,
+ 0x42, 0xe7, 0xf7, 0x7e, 0x62, 0x93, 0xfb, 0xb6, 0x39, 0xca,
+ 0x07, 0x20, 0x4e, 0xbc, 0x6b, 0xd1, 0x1d, 0xb0, 0xae, 0x73,
+ 0x66, 0xcd, 0xd7, 0x1a, 0xbd, 0x0e, 0x27, 0x48, 0x0a, 0x63,
+ 0x06, 0x8d, 0x59, 0xa7, 0xea, 0x2d, 0x56, 0xd6 },
+ { 0x54, 0xff, 0x78, 0x84, 0x79, 0xb2, 0x5d, 0x71, 0xa1, 0xc9,
+ 0x98, 0x13, 0xff, 0x22, 0x25, 0xab, 0xae, 0x80, 0x45, 0x3f,
+ 0xbb, 0x1e, 0x5b, 0xd8, 0xa7, 0xf0, 0x44, 0x0c, 0x9f, 0x68,
+ 0x4f, 0x25, 0x33, 0x5c, 0xc4, 0xf8, 0x5d, 0x15, 0xdf, 0xbf,
+ 0xff, 0x3a, 0xba, 0x5c, 0x69, 0x62, 0x80, 0x46, 0x55, 0xce,
+ 0x84, 0x91, 0x58, 0x80, 0xcd, 0xaf, 0x8e, 0xe0, 0x0e, 0x1a,
+ 0x8e, 0xef, 0x6c, 0xc9, 0x4e, 0x01, 0x41, 0xae, 0x85, 0x02,
+ 0xaa, 0x89, 0x20, 0x73, 0x95, 0x4c, 0xd2, 0xe9, 0x6d, 0xdf,
+ 0x14, 0x42, 0xbf, 0x36, 0x7d, 0xd4, 0xc5, 0x31, 0x46, 0x71,
+ 0x6f, 0x79, 0xa9, 0x25, 0xe7, 0xe7, 0xbb, 0x48, 0x27, 0xfa,
+ 0x4e, 0xb2, 0x1f, 0x6b, 0x4c, 0x93, 0x46, 0x89, 0x2f, 0xe3,
+ 0x74, 0xcb, 0x4b, 0x9f, 0xd0, 0x33, 0x04, 0x8b, 0x5d, 0xe9,
+ 0xea, 0xb2, 0x1f, 0xf0, 0xe1, 0xd0, 0xfa, 0x79 },
+ { 0x8a, 0xdb, 0xad, 0x85, 0x3f, 0x18, 0x30, 0xfe, 0x4e, 0x4e,
+ 0x45, 0x73, 0xee, 0x30, 0xb2, 0x86, 0x8a, 0xcd, 0xa9, 0x65,
+ 0x9f, 0xa1, 0x01, 0xe6, 0x17, 0x87, 0x55, 0x00, 0x28, 0xc9,
+ 0x30, 0x2c, 0x06, 0x9e, 0x82, 0xdc, 0x36, 0x78, 0xa4, 0x27,
+ 0xd6, 0xa2, 0xc0, 0x1d, 0x8b, 0x6a, 0x6c, 0x6b, 0x28, 0x94,
+ 0x5e, 0x31, 0xc9, 0x55, 0xae, 0xad, 0x91, 0x53, 0x62, 0xdc,
+ 0xb7, 0x86, 0xea, 0x9f, 0x33, 0x9d, 0xf0, 0x81, 0x0c, 0xcd,
+ 0x9e, 0xc9, 0xc6, 0x8f, 0x1b, 0x3b, 0x4a, 0x2c, 0x08, 0xe3,
+ 0xbb, 0x74, 0xe5, 0x8f, 0xdc, 0xb0, 0xc0, 0x0f, 0xe3, 0x28,
+ 0x54, 0x41, 0x8d, 0xf9, 0x0d, 0x2b, 0x50, 0xa5, 0xa5, 0xad,
+ 0xc0, 0x41, 0x81, 0x15, 0xe2, 0x4a, 0x46, 0x04, 0xfa, 0x3b,
+ 0x21, 0xf6, 0x92, 0x26, 0x46, 0x5b, 0xe6, 0xf3, 0xa5, 0x1e,
+ 0x27, 0xc6, 0xee, 0x30, 0xde, 0x40, 0xb0, 0x68 },
+ { 0x73, 0x93, 0x00, 0x36, 0xc0, 0x94, 0x5e, 0x5f, 0xf3, 0x42,
+ 0xc1, 0xaa, 0x02, 0x7e, 0x71, 0xc1, 0xb7, 0x5c, 0x41, 0xa6,
+ 0x66, 0xcb, 0xc9, 0x6c, 0xf5, 0x88, 0xb4, 0xf8, 0x17, 0x17,
+ 0xe1, 0xaf, 0x14, 0xeb, 0x86, 0xf3, 0x58, 0x40, 0x7a, 0x1d,
+ 0xdb, 0xe3, 0x86, 0xcb, 0x81, 0x6c, 0x07, 0x30, 0x40, 0x3f,
+ 0x16, 0x8c, 0x30, 0x26, 0xcd, 0x41, 0x95, 0xb1, 0x6c, 0xcc,
+ 0xcd, 0x5e, 0x87, 0xe7, 0x40, 0xd8, 0x6f, 0x30, 0x12, 0x43,
+ 0xf3, 0xef, 0x40, 0x90, 0xcf, 0xa6, 0x1b, 0x46, 0x4b, 0x28,
+ 0xcd, 0xbc, 0x2a, 0xd2, 0x09, 0x84, 0xfb, 0x0e, 0x6a, 0xa1,
+ 0xf5, 0xde, 0x8e, 0x1c, 0x0f, 0x7f, 0x45, 0x6b, 0x9c, 0xf2,
+ 0xe2, 0x33, 0x6d, 0x4f, 0x3c, 0xec, 0x67, 0x66, 0x7c, 0xc1,
+ 0xfc, 0xc2, 0xf4, 0x2f, 0xda, 0xf7, 0xf3, 0x9b, 0xcc, 0x79,
+ 0x06, 0x0a, 0xe1, 0x1f, 0x09, 0x69, 0xd5, 0x24 },
+ { 0x8b, 0xc6, 0xec, 0x4a, 0xe4, 0x29, 0x65, 0xe2, 0x5b, 0xd1,
+ 0x01, 0x82, 0xaa, 0x7c, 0x99, 0xd3, 0x9c, 0x28, 0xa9, 0x67,
+ 0x73, 0xea, 0xf2, 0x23, 0xcf, 0x56, 0x13, 0x48, 0xe0, 0x96,
+ 0x1b, 0x31, 0x45, 0xb9, 0xe6, 0x1b, 0x73, 0x1f, 0xc4, 0x47,
+ 0x61, 0xa5, 0x14, 0xe1, 0xb5, 0x24, 0x63, 0x2f, 0x43, 0x4a,
+ 0xc7, 0xb1, 0x64, 0xac, 0x8f, 0x15, 0x70, 0x5d, 0xdd, 0x5a,
+ 0xd9, 0x11, 0x08, 0xcc, 0xda, 0xcd, 0xfd, 0x5d, 0xd2, 0x9c,
+ 0x01, 0xaa, 0x4b, 0xd7, 0xd6, 0x9d, 0x61, 0x17, 0x9c, 0xae,
+ 0x17, 0x15, 0x90, 0x3e, 0x6a, 0x4f, 0x69, 0x85, 0x92, 0xb3,
+ 0x05, 0xd1, 0x02, 0x2c, 0xeb, 0x91, 0x69, 0x64, 0x2e, 0x08,
+ 0xf1, 0x8f, 0xd5, 0xbc, 0x8b, 0x98, 0x68, 0x19, 0xf5, 0x51,
+ 0x4f, 0x25, 0x78, 0x8b, 0x59, 0x1d, 0xf4, 0x18, 0x1a, 0xab,
+ 0x95, 0x4f, 0x75, 0x7d, 0x22, 0xcd, 0xaf, 0x42 },
+ { 0x8e, 0x85, 0x43, 0x7d, 0xbe, 0x9c, 0x7e, 0x15, 0x2b, 0x3c,
+ 0x8f, 0x71, 0xdc, 0xeb, 0x89, 0x55, 0xab, 0x01, 0x2c, 0x2c,
+ 0x58, 0x47, 0xa4, 0xd7, 0x28, 0x44, 0xd9, 0x6a, 0x98, 0x2f,
+ 0xc0, 0xd4, 0xd6, 0xa7, 0xdf, 0x0d, 0xaa, 0x60, 0xaa, 0x6a,
+ 0xd3, 0x08, 0xfc, 0x21, 0xae, 0x9b, 0x2a, 0xa8, 0xfc, 0x9a,
+ 0xc3, 0xb9, 0x48, 0xd6, 0x5c, 0xbb, 0xe5, 0x65, 0x43, 0x1c,
+ 0x8b, 0x65, 0xc9, 0xa1, 0xe3, 0x14, 0x71, 0xee, 0x6b, 0xe6,
+ 0xc8, 0xca, 0x73, 0x24, 0x83, 0xe3, 0x51, 0xb7, 0xda, 0x61,
+ 0xa0, 0xac, 0xfc, 0xa2, 0x2b, 0x29, 0xb2, 0xb7, 0x51, 0x0e,
+ 0x18, 0x60, 0x84, 0x57, 0xaa, 0x6e, 0x66, 0x55, 0xfc, 0x9c,
+ 0xbb, 0x60, 0x54, 0xa6, 0x06, 0xfe, 0x43, 0x7c, 0x40, 0x1e,
+ 0x36, 0x0c, 0xff, 0x54, 0x80, 0x0c, 0x09, 0x38, 0x8a, 0x30,
+ 0xd0, 0x96, 0xe5, 0xc0, 0xe7, 0xf2, 0xa3, 0x2b },
+};
+
+/*
+ * Loop for modular exponentiate the value in F_p*.
+ *
+ * Using 8-bit stripe table.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] b MP integer that is the base to exponentiate.
+ * @param [in] e MP integer that is the exponent.
+ * @param [out] c Result of exponentiation.
+ * @param [in] mp Multiplier to use when converting from Montgomery form.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_modexp_loop(SakkeKey* key, const mp_int* b, mp_int* e,
+ mp_proj* c, mp_digit mp)
+{
+ int err = 0;
+ mp_int* t1 = &key->tmp.m1;
+ mp_int* t2 = &key->tmp.m2;
+ mp_int* by = key->tmp.p1->z;
+ mp_int* prime = &key->params.prime;
+ unsigned char eb[128];
+ int i;
+ int y;
+
+ /* Use table for values of b exponentiated. */
+ (void)b;
+
+ (void)mp_to_unsigned_bin_len(e, eb, sizeof(eb));
+
+ /* Set the working value to the base in PF_p[q] */
+ err = mp_montgomery_calc_normalization(c->x, prime);
+ if (err == 0) {
+ y = (eb[112] >> 7) & 1;
+ y |= ((eb[ 96] >> 7) & 1) << 1;
+ y |= ((eb[ 80] >> 7) & 1) << 2;
+ y |= ((eb[ 64] >> 7) & 1) << 3;
+ y |= ((eb[ 48] >> 7) & 1) << 4;
+ y |= ((eb[ 32] >> 7) & 1) << 5;
+ y |= ((eb[ 16] >> 7) & 1) << 6;
+ y |= ((eb[ 0] >> 7) & 1) << 7;
+
+ (void)mp_read_unsigned_bin(c->y, sakke_1024_g_table[y], 128);
+ }
+ for (i = 128 - 2; (err == 0) && (i >= 0); i--) {
+ y = (eb[127 - i / 8 ] >> (i & 0x7)) & 1;
+ y |= ((eb[127 - (i / 8 + 16)] >> (i & 0x7)) & 1) << 1;
+ y |= ((eb[127 - (i / 8 + 32)] >> (i & 0x7)) & 1) << 2;
+ y |= ((eb[127 - (i / 8 + 48)] >> (i & 0x7)) & 1) << 3;
+ y |= ((eb[127 - (i / 8 + 64)] >> (i & 0x7)) & 1) << 4;
+ y |= ((eb[127 - (i / 8 + 80)] >> (i & 0x7)) & 1) << 5;
+ y |= ((eb[127 - (i / 8 + 96)] >> (i & 0x7)) & 1) << 6;
+ y |= ((eb[127 - (i / 8 + 112)] >> (i & 0x7)) & 1) << 7;
+
+ err = sakke_proj_sqr(c, prime, mp, c, t1, t2);
+ if (err == 0) {
+ (void)mp_read_unsigned_bin(by, sakke_1024_g_table[y], 128);
+ err = sakke_proj_mul_qx1(c, by, prime, mp, c, t1, t2);
+ }
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_SAKKE_SMALL */
+
+/*
+ * Modular exponentiate the value in F_p*.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] b MP integer that is the base to exponentiate.
+ * @param [in] e MP integer that is the exponent.
+ * @param [out] r Result of exponentiation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_modexp(SakkeKey* key, mp_int* b, mp_int* e, mp_int* r)
+{
+ int err;
+ mp_digit mp;
+ mp_int* prime = &key->params.prime;
+ mp_proj* c = key->tmp.p1;
+
+ (void)b;
+
+ err = mp_montgomery_setup(prime, &mp);
+ if (err == 0) {
+ err = sakke_modexp_loop(key, b, e, c, mp);
+ }
+
+ if (err == 0) {
+ err = mp_montgomery_reduce(c->x, prime, mp);
+ }
+ if (err == 0) {
+ err = mp_montgomery_reduce(c->y, prime, mp);
+ }
+ /* Convert value back from PF_p[q] to F_p* */
+ if (err == 0) {
+ err = mp_invmod(c->x, prime, c->x);
+ }
+ if (err == 0) {
+ err = mp_mulmod(c->x, c->y, prime, r);
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+/*
+ * Calculate the hash values h and v.
+ *
+ * RFC 6508, section 5.1, Steps 4.a and 4.b.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [in] hashSz Size of output of hash algorithm in bytes.
+ * @param [in] a Hash of data and extra.
+ * @param [in] h Rolling hash result.
+ * @param [out] v Output bytes of hashing.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when hashType is not supported.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_calc_h_v(SakkeKey* key, enum wc_HashType hashType,
+ word32 hashSz, const byte* a, byte* h, byte* v)
+{
+ int err;
+
+ /* Step 4.a: h_i = hashfn(h_(i - 1)) */
+ err = wc_HashUpdate(&key->hash, hashType, h, hashSz);
+ if (err == 0) {
+ err = wc_HashFinal(&key->hash, hashType, h);
+ }
+
+ /* Step 4.b: v_i = hashfn(h_i | A) */
+ if (err == 0) {
+ err = wc_HashUpdate(&key->hash, hashType, h, hashSz);
+ }
+ if (err == 0) {
+ err = wc_HashUpdate(&key->hash, hashType, a, hashSz);
+ }
+ if (err == 0) {
+ err = wc_HashFinal(&key->hash, hashType, v);
+ }
+
+ return err;
+}
+
+/*
+ * XOR hash output v into output, with length n, starting at index i.
+ *
+ * @param [in] v Output bytes of hashing.
+ * @param [in] hashSz Size of output of hash algorithm in bytes.
+ * @param [in,out] out Data to be XORed.
+ * @param [in] idx Index to start XORing into.
+ * @param [in] n Length of data to XOR (mask) in bytes.
+ */
+static void sakke_xor_in_v(const byte* v, word32 hashSz, byte* out, int idx,
+ int n)
+{
+ int o;
+ word32 i;
+
+ if (idx == 0) {
+ i = hashSz - (n % hashSz);
+ if (i == hashSz) {
+ i = 0;
+ }
+ }
+ else {
+ i = 0;
+ }
+ o = i;
+ for (; i < hashSz; i++) {
+ out[idx + i - o] ^= v[i];
+ }
+}
+
+/*
+ * Hash octet strings to an integer range.
+ *
+ * RFC 6508, section 5.1, Steps 1 to 4.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [in] data First block of data.
+ * @param [in] sz Size of first block of data in bytes.
+ * @param [in] extra Extra block of data.
+ * @param [in] extraSz Size of extra block of data in bytes.
+ * @param [out] a Output bytes of hashing.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when hashType is not supported.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_calc_a(SakkeKey* key, enum wc_HashType hashType,
+ const byte* data, word32 sz, const byte* extra, word32 extraSz, byte* a)
+{
+ int err;
+
+ /* Step 1: A = hashfn( s ), where s = data | extra */
+ err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID);
+ if (err == 0) {
+ err = wc_HashUpdate(&key->hash, hashType, data, sz);
+ }
+ if ((err == 0) && (extra != NULL)) {
+ err = wc_HashUpdate(&key->hash, hashType, extra, extraSz);
+ }
+ if (err == 0) {
+ err = wc_HashFinal(&key->hash, hashType, a);
+ }
+
+ return err;
+}
+
+/*
+ * Hash octet strings to an integer range.
+ *
+ * RFC 6508, section 5.1, Steps 1 to 4.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [in] a Hash of original data.
+ * @param [out] out Output bytes of hashing.
+ * @param [in] n Size of output buffer in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when hashType is not supported.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_hash_to_range(SakkeKey* key, enum wc_HashType hashType,
+ const byte* a, byte* out, word32 n)
+{
+ int err = 0;
+ byte h[WC_MAX_DIGEST_SIZE];
+ byte v[WC_MAX_DIGEST_SIZE];
+ word32 hashSz = wc_HashGetDigestSize(hashType);
+ word32 i;
+
+ /* Step 1: A = hashfn( s ), where s = data | extra
+ * See sakke_calc_a (need function parameters to be 7 or less)
+ */
+
+ /* Step 2: h_0 = 00...00, a string of null bits of length hashlen bits */
+ XMEMSET(h, 0, hashSz);
+
+ /* Step 3: l = Ceiling(lg(n)/hashlen) */
+ /* Step 4: For each i in 1 to l, do */
+ for (i = 0; (err == 0) && (i < n); i += hashSz) {
+ /* Steps 4.a and 4.b */
+ err = sakke_calc_h_v(key, hashType, hashSz, a, h, v);
+
+ /* XOR in the result into output buffer. */
+ if (err == 0) {
+ sakke_xor_in_v(v, hashSz, out, i, n);
+ }
+ }
+
+ return err;
+}
+
+/*
+ * Hash octet strings to an integer range - RFC 6508 section 5.1.
+ * Steps 1 to 6.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [in] a Hash of original data.
+ * @param [in] q MP integer representing modulus.
+ * @param [in] n Size of output in bytes.
+ * @param [out] r MP integer representing modulo reduced hashes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when hashType is not supported.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_hash_to_range_int(SakkeKey* key, enum wc_HashType hashType,
+ const byte* a, mp_int* q, word32 n, mp_int* r)
+{
+ int err;
+ byte* rb = key->data;
+
+ /* Make all zeros so that hash output can be XORed in. */
+ XMEMSET(rb, 0, n);
+
+ /* Steps 1-4 */
+ err = sakke_hash_to_range(key, hashType, a, rb, n);
+ if (err == 0) {
+ /* Steps 5 v' = v_1 | ... | v_l */
+ err = mp_read_unsigned_bin(r, rb, n);
+ }
+ if (err == 0) {
+ /* Steps 6 v = v' mod n */
+ err = mp_mod(r, q, r);
+ }
+
+ return err;
+}
+
+/**
+ * Set the identity to perform operations with.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] id Identity.
+ * @param [in] idSz Size of identity in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or id is NULL or idSz > SAKKE_ID_MAX_SIZE.
+ */
+int wc_SetSakkeIdentity(SakkeKey* key, const byte* id, word16 idSz)
+{
+ int err = 0;
+
+ if ((key == NULL) || (id == NULL) || (idSz > SAKKE_ID_MAX_SIZE)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ if (err == 0) {
+ XMEMCPY(key->id, id, idSz);
+ key->idSz = idSz;
+ }
+
+ return err;
+}
+
+/**
+ * Compute the elliptic curve point I for identity. Partial for point R.
+ *
+ * RFC 6508, Section 6.2.1, Step 3.\n
+ * RFC 6508, Section 6.2.2, Step 5.\n
+ * I = [b]P + Z_S
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] id Identity.
+ * @param [in] idSz Size of identity in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or id is NULL or idSz > SAKKE_ID_MAX_SIZE.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_MakeSakkePointI(SakkeKey* key, const byte* id, word16 idSz)
+{
+ int err = 0;
+
+ if ((key == NULL) || (id == NULL) || (idSz > SAKKE_ID_MAX_SIZE)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ /* I = [b]P + Z_S */
+ err = sakke_compute_point_i(key, id, idSz, key->i.i);
+ }
+ if (err == 0) {
+ XMEMCPY(key->i.id, id, idSz);
+ key->i.idSz = idSz;
+ }
+
+ return err;
+}
+
+/**
+ * Get the elliptic curve point I - a partial calculation for point R.
+ *
+ * RFC 6508, Section 6.2.1, Step 3.\n
+ * RFC 6508, Section 6.2.2, Step 5.\n
+ * I = [b]P + Z_S
+ *
+ * @param [in] key SAKKE key.
+ * @param [out] data Encoding of point I.
+ * @param [in,out] sz On in, the size of data in bytes.
+ * On out, the size of the encoding in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or sz is NULL.
+ * @return LENGTH_ONLY_E when data is NULL. Number of bytes required returned
+ * in sz.
+ * @return BUFFER_E when sz is too small to hold encoding.
+ */
+int wc_GetSakkePointI(SakkeKey* key, byte* data, word32* sz)
+{
+ int err = 0;
+
+ if ((key == NULL) || (sz == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ if ((err == 0) && (data == NULL)) {
+ *sz = key->ecc.dp->size * 2;
+ err = LENGTH_ONLY_E;
+ }
+ if ((err == 0) && (*sz < (word32)key->ecc.dp->size * 2)) {
+ err = BUFFER_E;
+ }
+
+ if (err == 0) {
+ /* Write out the x ordinate into key size bytes. */
+ err = mp_to_unsigned_bin_len(key->i.i->x, data, key->ecc.dp->size);
+ }
+ if (err == 0) {
+ data += key->ecc.dp->size;
+ /* Write data the y ordinate into key size bytes. */
+ err = mp_to_unsigned_bin_len(key->i.i->y, data, key->ecc.dp->size);
+ }
+ if (err == 0) {
+ *sz = key->ecc.dp->size * 2;
+ }
+
+ return err;
+}
+
+/**
+ * Set the elliptic curve point I - a partial calucation for point R - and the
+ * identity that it belongs to.
+ *
+ * RFC 6508, Section 6.2.1, Step 3.\n
+ * RFC 6508, Section 6.2.2, Step 5.\n
+ * I = [b]P + Z_S
+ *
+ * @param [in] key SAKKE key.
+ * @param [out] data Encoding of point I.
+ * @param [in,out] sz On in, the size of data in bytes.
+ * On out, the size of the encoding in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key, id or data is NULL.
+ * @return BUFFER_E when idSz is too big to store or sz is not the required
+ * size.
+ */
+int wc_SetSakkePointI(SakkeKey* key, const byte* id, word16 idSz,
+ const byte* data, word32 sz)
+{
+ int err = 0;
+
+ if ((key == NULL) || (id == NULL) || (data == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+ if ((err == 0) && ((idSz > SAKKE_ID_MAX_SIZE) ||
+ (sz != (word32)key->ecc.dp->size * 2))) {
+ err = BUFFER_E;
+ }
+
+ if (err == 0) {
+ /* Read the x value from key size bytes. */
+ err = mp_read_unsigned_bin(key->i.i->x, data, key->ecc.dp->size);
+ }
+ if (err == 0) {
+ data += key->ecc.dp->size;
+ /* Read the y value from key size bytes. */
+ err = mp_read_unsigned_bin(key->i.i->y, data, key->ecc.dp->size);
+ }
+ if (err == 0) {
+ err = mp_set(key->i.i->z, 1);
+ }
+ if (err == 0) {
+ XMEMCPY(key->i.id, id, idSz);
+ key->i.idSz = idSz;
+ }
+
+ return err;
+}
+
+/**
+ * Generate the pre-computation table for point I.
+ *
+ * A reference to the table is stored if successfully generated.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in,out] table Pre-computation table.
+ * NULL to indicate that only length required.
+ * @param [in,out] len On in, the size of table buffer in bytes.
+ * On out, the size of table data in bytes.
+ * @return BAD_FUNC_ARG then key or len is NULL.
+ * @return LENGTH_ONLY_E when only the length is returned.
+ * @return BUFFER_E when len is too small.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int wc_GenerateSakkePointITable(SakkeKey* key, byte* table, word32* len)
+{
+ int err = 0;
+
+ if ((key == NULL) || (len == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+ if (err == 0) {
+ err = sp_ecc_gen_table_1024(key->i.i, table, len, key->heap);
+ }
+ if (err == 0) {
+ key->i.table = table;
+ key->i.tableLen = *len;
+ }
+#else
+ if ((err == 0) && (table == NULL)) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ if ((err == 0) && (*len != 0)) {
+ *len = 0;
+ err = BUFFER_E;
+ }
+ if (err == 0) {
+ *len = 0;
+ key->i.table = table;
+ key->i.tableLen = *len;
+ }
+ (void)table;
+#endif
+
+ return err;
+}
+
+/**
+ * Sets the pre-computation table for point I.
+ * Speeds up making and deriving the encapsulated SSV.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] table Pre-computation table for Point I.
+ * @param [in] len Length of pre-computation table in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key or table is NULL.
+ */
+int wc_SetSakkePointITable(SakkeKey* key, byte* table, word32 len)
+{
+ int err = 0;
+#ifdef WOLFSSL_HAVE_SP_ECC
+ word32 sz = 0;
+#endif
+
+ if ((key == NULL) || (table == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+ if (err == 0) {
+ err = sp_ecc_gen_table_1024(key->i.i, NULL, &sz, NULL);
+ if (err == LENGTH_ONLY_E) {
+ err = 0;
+ }
+ }
+ if ((err == 0) && (len != sz)) {
+ err = BUFFER_E;
+ }
+#else
+ if ((err == 0) && (len != 0)) {
+ err = BUFFER_E;
+ }
+#endif
+
+ if (err == 0) {
+ key->i.table = table;
+ key->i.tableLen = len;
+ }
+
+ return err;
+}
+
+/**
+ * Clears the pre-computation table for point I.
+ *
+ * Must be called once the table has been disposed of.
+ *
+ * @param [in] key SAKKE key.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key is NULL.
+ */
+int wc_ClearSakkePointITable(SakkeKey* key)
+{
+ int err = 0;
+
+ if (key == NULL) {
+ err = BAD_FUNC_ARG;
+ }
+
+ if (err == 0) {
+ key->i.table = NULL;
+ key->i.tableLen = 0;
+ }
+
+ return err;
+}
+
+/*
+ * Compute the elliptic curve point R for device B.
+ *
+ * RFC 6508, Section 6.2.1, Step 3.\n
+ * RFC 6508, Section 6.2.2, Step 5.\n
+ * R = [r]([b]P + Z_S)
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] id Identifier to of device B.
+ * @param [in] idSz Size of identifier in bytes.
+ * @param [in] z ECC point - KMS Public Key Z_S.
+ * @param [in] n Number of bytes in r.
+ * @param [in] out Result R encoded to bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sakke_compute_point_r(SakkeKey* key, const byte* id, word16 idSz,
+ const mp_int* r, word32 n, byte* out)
+{
+ int err = 0;
+ ecc_point* i = key->i.i;
+ ecc_point* rp = key->tmp.p2;
+ word32 sz;
+
+ if ((key->i.idSz == 0) || (key->i.idSz != idSz) ||
+ (XMEMCMP(id, key->i.id, idSz) != 0)) {
+ /* I = [b]P + Z_S */
+ err = sakke_compute_point_i(key, id, idSz, i);
+ if ((err == 0) && (idSz <= SAKKE_ID_MAX_SIZE)) {
+ XMEMCPY(key->i.id, id, idSz);
+ key->i.idSz = idSz;
+ }
+ key->i.table = NULL;
+ key->i.tableLen = 0;
+ }
+ /* [r]([b]P + Z_S) */
+ if (err == 0) {
+ err = sakke_mulmod_point(key, r, i, key->i.table, rp, 1);
+ }
+ /* Export to canonical form */
+ if (err == 0) {
+ sz = n * 2 + 1;
+ err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(key->ecc.dp->id), rp,
+ out, &sz);
+ }
+
+ return err;
+}
+
+/**
+ * Makes the Shared Secret Value (SSV) encapsulated and returns the
+ * authentication data.
+ *
+ * RFC 6508, Section 6.2.1.
+ *
+ * SSV is overwritten with encapsulated SSV.
+ *
+ * Call wc_SetSakkeIdentity() to set the identity to use with operation.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in,out] ssv On in, Shared Secret Value (SSV) data.
+ * On out, encrypted Shared Secret Value (SSV) data.
+ * @param [in] ssvSz Size of SSV in bytes.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [out] auth Authentication data.
+ * @param [out] authSz Size of authentication data in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key, ssv or encSz is NULL, ssvSz is to big or
+ * encSz is too small.
+ * @return BAD_STATE_E when identity not set.
+ * @return LENGTH_ONLY_E when auth is NULL. authSz contains required size of
+ * auth in bytes.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, enum wc_HashType hashType,
+ byte* ssv, word16 ssvSz, byte* auth, word16* authSz)
+{
+ int err = 0;
+ mp_int* r = NULL;
+ word16 n = 0;
+ word16 outSz = 0;
+ byte a[WC_MAX_DIGEST_SIZE];
+
+ if ((key == NULL) || (ssv == NULL) || (authSz == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+ if ((err == 0) && (key->idSz == 0)) {
+ err = BAD_STATE_E;
+ }
+
+ /* Load parameters */
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8);
+
+ /* Uncompressed point */
+ outSz = 1 + 2 * n;
+
+ if ((auth != NULL) && (*authSz < outSz)) {
+ err = BAD_FUNC_ARG;
+ }
+ }
+ if (err == 0) {
+ *authSz = outSz;
+
+ if (auth == NULL) {
+ err = LENGTH_ONLY_E;
+ }
+ }
+
+ if (err == 0) {
+ err = sakke_load_base_point(key);
+ }
+ if (err == 0) {
+ err = sakke_load_pairing_base(key);
+ }
+
+ /* Step 1: Generate a random SSV 0..(2^n)-1
+ * Already generated - see wc_MakeSakkeEncapsulated()
+ */
+ /* Step 2: Compute r = HashToIntegerRange( SSV | b, q, Hash ) */
+ if (err == 0) {
+ err = sakke_calc_a(key, hashType, ssv, ssvSz, key->id, key->idSz, a);
+ }
+ if (err == 0) {
+ r = key->tmp.p3->z;
+ err = sakke_hash_to_range_int(key, hashType, a, &key->params.q, n, r);
+ }
+ /* Step 3: Compute R_(b,S) = [r]([b]P + Z_S) in E(F_p) */
+ if (err == 0) {
+ err = sakke_compute_point_r(key, key->id, key->idSz, r, n, auth);
+ }
+
+ /* Step 4.a: Compute g^r */
+ if (err == 0) {
+ err = sakke_modexp(key, &key->params.g, r, r);
+ }
+
+ /* Step 4.b: Compute H := SSV XOR HashToIntegerRange( g^r, 2^n, Hash ) */
+ if (err == 0) {
+ err = mp_to_unsigned_bin_len(r, key->data, n);
+ }
+ /* ssv ^= HashToIntegerRange( g^r, 2^n, Hash ) */
+ if (err == 0) {
+ err = sakke_calc_a(key, hashType, key->data, n, NULL, 0, a);
+ }
+ if (err == 0) {
+ err = sakke_hash_to_range(key, hashType, a, ssv, ssvSz);
+ }
+
+ /* Step 5: Form the Encapsulated Data ( R_(b,S), H )
+ * R_(b,S) encoded in sakke_compute_point_r, H is a pointer into enc.
+ */
+
+ /* Step 6: Output SSV - already encoded in buffer */
+
+ return err;
+}
+
+/**
+ * Generate a random Shared Secret Value (SSV).
+ *
+ * RFC 6508, Section 6.2.1, Step 1.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] rng Random number generator.
+ * @param [out] ssv Shared Secret Value (SSV) data.
+ * @param [out] ssvSz Size of SSV in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key, rng or ssvSz is NULL or ssvSz is to small.
+ * @return LENGTH_ONLY_E when ssv is NULL. ssvSz contains the required size of
+ * in bytes.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, word16* ssvSz)
+{
+ int err = 0;
+ word16 n = 0;
+
+ if ((key == NULL) || (rng == NULL) || (ssvSz == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ /* Load parameters */
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8);
+
+ if ((ssv != NULL) && (*ssvSz > n)) {
+ err = BAD_FUNC_ARG;
+ }
+ }
+ if (err == 0) {
+ /* Return length only if an ouput buffer is NULL. */
+ if (ssv == NULL) {
+ *ssvSz = (word16) (n / 8);
+ err = LENGTH_ONLY_E;
+ }
+ else {
+ n = *ssvSz;
+ }
+ }
+
+ /* Step 1: Select a random ephemeral integer value. Range 0..(2^n - 1) */
+ if (err == 0) {
+ err = wc_RNG_GenerateBlock(rng, ssv, n);
+ }
+
+ return err;
+}
+
+/**
+ * Derive the Shared Secret Value from the encapsulated data using the set
+ * RSK
+ *
+ * RFC 6508, Section 6.2.2.
+ *
+ * Encapsulated SSV is overwritten with SSV.
+ *
+ * Call wc_SetSakkeIdentity() to set the identity to use with operation.
+ *
+ * Call wc_SetSakkeRSK() to set the Receiver Secret Key (RSK) to use with
+ * operation.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] hashType Hash algorithm to use.
+ * @param [in,out] ssv On in, encrypted Secret Shared Value (SSV) data.
+ * On out, Secret Shared Value (SSV) data.
+ * @param [in] ssvSz Size of SSV in bytes.
+ * @param [in] auth Authentication data.
+ * @param [in] authSz Size of authentication data in bytes.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when key, ssv or auth is NULL.
+ * @return BAD_STATE_E when RSK or identity not set.
+ * @return SAKKE_VERIFY_FAIL_E when calculated R doesn't match the encapsulated
+ * data's R.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, byte* ssv,
+ word16 ssvSz, const byte* auth, word16 authSz)
+{
+ int err = 0;
+ word16 n = 0;
+ ecc_point* r = NULL;
+ mp_int* w = NULL;
+ mp_int* ri = NULL;
+ byte* wb = NULL;
+ byte* test = NULL;
+ byte a[WC_MAX_DIGEST_SIZE] = {0};
+
+ if ((key == NULL) || (ssv == NULL) || (auth == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+ if ((err == 0) && (!key->rsk.set || (key->idSz == 0))) {
+ err = BAD_STATE_E;
+ }
+
+ /* Load parameters */
+ if (err == 0) {
+ err = sakke_load_params(key);
+ }
+ if (err == 0) {
+ n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8);
+
+ if (authSz != 2 * n + 1) {
+ err = BAD_FUNC_ARG;
+ }
+ }
+ if (err == 0) {
+ err = sakke_load_base_point(key);
+ }
+
+ /* Step 1: Parse the Encapsulated Data ( R_(b,S), H )
+ * H = auth, so already extracted. */
+ if (err == 0) {
+ r = key->tmp.p2;
+
+ err = wc_ecc_import_point_der(auth, n * 2 + 1,
+ wc_ecc_get_curve_idx(key->ecc.dp->id), r);
+ }
+
+ /* Step 2: w = < R_(b,S), K_(b,S) > = < K_(b,S), R_(b,S) > = < rsk , r > */
+ if (err == 0) {
+ w = &key->tmp.m1;
+
+ err = sakke_pairing(key, key->rsk.rsk, r, w, key->rsk.table,
+ key->rsk.tableLen);
+ }
+
+ /* Step 3: Compute SSV = H XOR HashToIntegerRange( w, 2^n, Hash ) */
+ if (err == 0) {
+ wb = key->data;
+ err = mp_to_unsigned_bin_len(w, wb, n);
+ }
+ /* HashToIntegerRange( w, 2^n, Hash ) */
+ if (err == 0) {
+ err = sakke_calc_a(key, hashType, wb, n, NULL, 0, a);
+ }
+ if (err == 0) {
+ err = sakke_hash_to_range(key, hashType, a, ssv, ssvSz);
+ }
+
+ /* Step 4: r = HashToIntegerRange( SSV | b, q, Hash ) */
+ if (err == 0) {
+ err = sakke_calc_a(key, hashType, ssv, ssvSz, key->id, key->idSz, a);
+ }
+ if (err == 0) {
+ ri = &key->tmp.m1;
+ err = sakke_hash_to_range_int(key, hashType, a, &key->params.q, n, ri);
+ }
+
+ /* Step 5: Compute TEST = [r]([b]P + Z_S) == R_(b,S) */
+ if (err == 0) {
+ test = key->data;
+
+ err = sakke_compute_point_r(key, key->id, key->idSz, ri, n, test);
+ }
+ if ((err == 0) && (XMEMCMP(auth, test, 2 * n + 1) != 0)) {
+ err = SAKKE_VERIFY_FAIL_E;
+ }
+
+ return err;
+}
+#endif /* WOLFCRYPT_SAKKE_CLIENT */
+
+#endif /* WOLFCRYPT_HAVE_SAKKE */
+
diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c
index 3ee43f4ab..53f6378e7 100644
--- a/wolfcrypt/src/sha256.c
+++ b/wolfcrypt/src/sha256.c
@@ -167,6 +167,9 @@ where 0 <= L < 2^64.
#ifndef NO_AVX2_SUPPORT
#define HAVE_INTEL_AVX2
#endif
+#else
+ #undef HAVE_INTEL_AVX1
+ #undef HAVE_INTEL_AVX2
#endif /* USE_INTEL_SPEEDUP */
#if defined(HAVE_INTEL_AVX2)
@@ -841,7 +844,7 @@ static int InitSha256(wc_Sha256* sha256)
S[i] = sha256->digest[i];
for (i = 0; i < 16; i++)
- W[i] = *((word32*)&data[i*sizeof(word32)]);
+ W[i] = *((const word32*)&data[i*sizeof(word32)]);
for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++)
W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c
index 8cd9c9d58..799d69649 100644
--- a/wolfcrypt/src/sha3.c
+++ b/wolfcrypt/src/sha3.c
@@ -554,7 +554,7 @@ static word64 Load64BitBigEndian(const byte* a)
return n;
#else
- return *(word64*)a;
+ return *(const word64*)a;
#endif
}
@@ -1193,7 +1193,7 @@ int wc_Shake256_Final(wc_Shake* shake, byte* hash, word32 hashLen)
return BAD_FUNC_ARG;
}
- ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, hashLen);
+ ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, (byte)hashLen);
if (ret != 0)
return ret;
diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c
index d2f8c8907..2af49347f 100644
--- a/wolfcrypt/src/sp_arm32.c
+++ b/wolfcrypt/src/sp_arm32.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -58,7 +58,8 @@
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -100,7 +101,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -134,7 +136,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -173,7 +177,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 2048 / 8 - 1;
a[j] = 0;
@@ -215,66 +222,60 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"sub sp, sp, #32\n\t"
"mov r10, #0\n\t"
"# A[0] * B[0]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r3, r4, r8, r9\n\t"
+ "ldr r11, [%[a], #0]\n\t"
+ "ldr r12, [%[b], #0]\n\t"
+ "umull r3, r4, r11, r12\n\t"
"mov r5, #0\n\t"
"str r3, [sp]\n\t"
"# A[0] * B[1]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[1] * B[0]\n\t"
"ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #4]\n\t"
+ "# A[2] * B[0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[1]\n\t"
+ "ldr r11, [%[a], #4]\n\t"
+ "ldr r12, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[0] * B[2]\n\t"
"ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[1] * B[1]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[0]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #8]\n\t"
"# A[0] * B[3]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
"# A[1] * B[2]\n\t"
- "ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[2] * B[1]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -286,13 +287,25 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #12]\n\t"
- "# A[0] * B[4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[4] * B[0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
+ "# A[3] * B[1]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[2]\n\t"
+ "ldr r11, [%[a], #8]\n\t"
+ "ldr r12, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[1] * B[3]\n\t"
"ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #12]\n\t"
@@ -300,30 +313,15 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[2] * B[2]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[1]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[0]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #16]\n\t"
"# A[0] * B[5]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
@@ -337,16 +335,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[2] * B[3]\n\t"
- "ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[3] * B[2]\n\t"
"ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -365,20 +361,32 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #20]\n\t"
- "# A[0] * B[6]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[6] * B[0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
- "# A[1] * B[5]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #20]\n\t"
+ "# A[5] * B[1]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
+ "# A[4] * B[2]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[3]\n\t"
+ "ldr r11, [%[a], #12]\n\t"
+ "ldr r12, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[2] * B[4]\n\t"
"ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #16]\n\t"
@@ -386,37 +394,22 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[3] * B[3]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[1] * B[5]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[4] * B[2]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[1]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[0]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[6]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #24]\n\t"
"# A[0] * B[7]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
@@ -437,16 +430,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[3] * B[4]\n\t"
- "ldr r8, [%[a], #12]\n\t"
"ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[4] * B[3]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -472,20 +463,32 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #28]\n\t"
- "# A[1] * B[7]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #28]\n\t"
+ "# A[7] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
- "# A[2] * B[6]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[6] * B[2]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
+ "# A[5] * B[3]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[4]\n\t"
+ "ldr r11, [%[a], #16]\n\t"
+ "ldr r12, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[3] * B[5]\n\t"
"ldr r8, [%[a], #12]\n\t"
"ldr r9, [%[b], #20]\n\t"
@@ -493,30 +496,16 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[4] * B[4]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[2] * B[6]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[5] * B[3]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[6] * B[2]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[7] * B[1]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[1] * B[7]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -524,7 +513,6 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r5, [%[r], #32]\n\t"
"# A[2] * B[7]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -537,16 +525,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[4] * B[5]\n\t"
- "ldr r8, [%[a], #16]\n\t"
"ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[5] * B[4]\n\t"
"ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -565,13 +551,25 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #36]\n\t"
- "# A[3] * B[7]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #28]\n\t"
+ "# A[7] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
+ "# A[6] * B[4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[5]\n\t"
+ "ldr r11, [%[a], #20]\n\t"
+ "ldr r12, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[4] * B[6]\n\t"
"ldr r8, [%[a], #16]\n\t"
"ldr r9, [%[b], #24]\n\t"
@@ -579,23 +577,9 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[5] * B[5]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[6] * B[4]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[7] * B[3]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[3] * B[7]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -603,22 +587,19 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r4, [%[r], #40]\n\t"
"# A[4] * B[7]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
"# A[5] * B[6]\n\t"
- "ldr r8, [%[a], #20]\n\t"
"ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[6] * B[5]\n\t"
"ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -630,71 +611,52 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [%[r], #44]\n\t"
+ "# A[7] * B[5]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[6] * B[6]\n\t"
+ "ldr r11, [%[a], #24]\n\t"
+ "ldr r12, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[5] * B[7]\n\t"
"ldr r8, [%[a], #20]\n\t"
"ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r10, r10\n\t"
- "# A[6] * B[6]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[7] * B[5]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[6] * B[7]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[7] * B[6]\n\t"
"ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[7] * B[7]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adc r3, r3, r7\n\t"
"str r5, [%[r], #56]\n\t"
"str r3, [%[r], #60]\n\t"
- "ldr r3, [sp, #0]\n\t"
- "ldr r4, [sp, #4]\n\t"
- "ldr r5, [sp, #8]\n\t"
- "ldr r6, [sp, #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [sp, #16]\n\t"
- "ldr r4, [sp, #20]\n\t"
- "ldr r5, [sp, #24]\n\t"
- "ldr r6, [sp, #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "add sp, sp, #32\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "sub %[r], %[r], #32\n\t"
:
: [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@@ -707,7 +669,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
{
__asm__ __volatile__ (
"sub sp, sp, #32\n\t"
- "mov r14, #0\n\t"
+ "mov r12, #0\n\t"
"# A[0] * A[0]\n\t"
"ldr r10, [%[a], #0]\n\t"
"umull r8, r3, r10, r10\n\t"
@@ -719,10 +681,10 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [sp, #4]\n\t"
"# A[0] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
@@ -730,16 +692,16 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
+ "adc r3, r12, r12\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"# A[1] * A[1]\n\t"
"ldr r10, [%[a], #4]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"str r4, [sp, #8]\n\t"
"# A[0] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
@@ -747,20 +709,20 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
+ "adc r4, r12, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"# A[1] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
"ldr r8, [%[a], #4]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"str r2, [sp, #12]\n\t"
"# A[0] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
@@ -768,26 +730,26 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[1] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"ldr r8, [%[a], #4]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[2] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [sp, #16]\n\t"
"# A[0] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
@@ -801,14 +763,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -828,14 +790,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -844,7 +806,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r2, r2, r5\n\t"
"adcs r3, r3, r6\n\t"
"adc r4, r4, r7\n\t"
@@ -861,21 +823,21 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -895,14 +857,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -911,7 +873,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r4, r4, r5\n\t"
"adcs r2, r2, r6\n\t"
"adc r3, r3, r7\n\t"
@@ -928,14 +890,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -949,26 +911,26 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[4] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[5] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [%[r], #40]\n\t"
"# A[4] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
@@ -976,20 +938,20 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
+ "adc r3, r12, r12\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"# A[5] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #20]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"str r4, [%[r], #44]\n\t"
"# A[5] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
@@ -997,16 +959,16 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
+ "adc r4, r12, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"# A[6] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"str r2, [%[r], #48]\n\t"
"# A[6] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
@@ -1014,10 +976,10 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [%[r], #52]\n\t"
"# A[7] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
@@ -1026,26 +988,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
"adc r2, r2, r9\n\t"
"str r4, [%[r], #56]\n\t"
"str r2, [%[r], #60]\n\t"
- "ldr r2, [sp, #0]\n\t"
- "ldr r3, [sp, #4]\n\t"
- "ldr r4, [sp, #8]\n\t"
- "ldr r8, [sp, #12]\n\t"
- "str r2, [%[r], #0]\n\t"
- "str r3, [%[r], #4]\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r8, [%[r], #12]\n\t"
- "ldr r2, [sp, #16]\n\t"
- "ldr r3, [sp, #20]\n\t"
- "ldr r4, [sp, #24]\n\t"
- "ldr r8, [sp, #28]\n\t"
- "str r2, [%[r], #16]\n\t"
- "str r3, [%[r], #20]\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r8, [%[r], #28]\n\t"
- "add sp, sp, #32\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "sub %[r], %[r], #32\n\t"
:
: [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
+ : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12"
);
}
@@ -1312,7 +1262,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
sp_digit a1[8];
sp_digit b1[8];
sp_digit z2[16];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_8(a1, a, &a[8]);
cb = sp_2048_add_8(b1, b, &b[8]);
@@ -1699,7 +1651,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
sp_digit a1[16];
sp_digit b1[16];
sp_digit z2[32];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_16(a1, a, &a[16]);
cb = sp_2048_add_16(b1, b, &b[16]);
@@ -2342,7 +2296,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
sp_digit a1[32];
sp_digit b1[32];
sp_digit z2[64];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_32(a1, a, &a[32]);
cb = sp_2048_add_32(b1, b, &b[32]);
@@ -2857,7 +2813,7 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -2866,7 +2822,8 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -2875,7 +2832,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -2925,499 +2882,437 @@ static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #44]\n\t"
"# A[12] * B\n\t"
"ldr r8, [%[a], #48]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[13] * B\n\t"
"ldr r8, [%[a], #52]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[14] * B\n\t"
"ldr r8, [%[a], #56]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #56]\n\t"
"# A[15] * B\n\t"
"ldr r8, [%[a], #60]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #60]\n\t"
"# A[16] * B\n\t"
"ldr r8, [%[a], #64]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #64]\n\t"
"# A[17] * B\n\t"
"ldr r8, [%[a], #68]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #68]\n\t"
"# A[18] * B\n\t"
"ldr r8, [%[a], #72]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #72]\n\t"
"# A[19] * B\n\t"
"ldr r8, [%[a], #76]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #76]\n\t"
"# A[20] * B\n\t"
"ldr r8, [%[a], #80]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[21] * B\n\t"
"ldr r8, [%[a], #84]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[22] * B\n\t"
"ldr r8, [%[a], #88]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #88]\n\t"
"# A[23] * B\n\t"
"ldr r8, [%[a], #92]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #92]\n\t"
"# A[24] * B\n\t"
"ldr r8, [%[a], #96]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #96]\n\t"
"# A[25] * B\n\t"
"ldr r8, [%[a], #100]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #100]\n\t"
"# A[26] * B\n\t"
"ldr r8, [%[a], #104]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #104]\n\t"
"# A[27] * B\n\t"
"ldr r8, [%[a], #108]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #108]\n\t"
"# A[28] * B\n\t"
"ldr r8, [%[a], #112]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #112]\n\t"
"# A[29] * B\n\t"
"ldr r8, [%[a], #116]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #116]\n\t"
"# A[30] * B\n\t"
"ldr r8, [%[a], #120]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #120]\n\t"
"# A[31] * B\n\t"
"ldr r8, [%[a], #124]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #124]\n\t"
"# A[32] * B\n\t"
"ldr r8, [%[a], #128]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #128]\n\t"
"# A[33] * B\n\t"
"ldr r8, [%[a], #132]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #132]\n\t"
"# A[34] * B\n\t"
"ldr r8, [%[a], #136]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #136]\n\t"
"# A[35] * B\n\t"
"ldr r8, [%[a], #140]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #140]\n\t"
"# A[36] * B\n\t"
"ldr r8, [%[a], #144]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #144]\n\t"
"# A[37] * B\n\t"
"ldr r8, [%[a], #148]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #148]\n\t"
"# A[38] * B\n\t"
"ldr r8, [%[a], #152]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #152]\n\t"
"# A[39] * B\n\t"
"ldr r8, [%[a], #156]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #156]\n\t"
"# A[40] * B\n\t"
"ldr r8, [%[a], #160]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #160]\n\t"
"# A[41] * B\n\t"
"ldr r8, [%[a], #164]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #164]\n\t"
"# A[42] * B\n\t"
"ldr r8, [%[a], #168]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #168]\n\t"
"# A[43] * B\n\t"
"ldr r8, [%[a], #172]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #172]\n\t"
"# A[44] * B\n\t"
"ldr r8, [%[a], #176]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #176]\n\t"
"# A[45] * B\n\t"
"ldr r8, [%[a], #180]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #180]\n\t"
"# A[46] * B\n\t"
"ldr r8, [%[a], #184]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #184]\n\t"
"# A[47] * B\n\t"
"ldr r8, [%[a], #188]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #188]\n\t"
"# A[48] * B\n\t"
"ldr r8, [%[a], #192]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #192]\n\t"
"# A[49] * B\n\t"
"ldr r8, [%[a], #196]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #196]\n\t"
"# A[50] * B\n\t"
"ldr r8, [%[a], #200]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #200]\n\t"
"# A[51] * B\n\t"
"ldr r8, [%[a], #204]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #204]\n\t"
"# A[52] * B\n\t"
"ldr r8, [%[a], #208]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #208]\n\t"
"# A[53] * B\n\t"
"ldr r8, [%[a], #212]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #212]\n\t"
"# A[54] * B\n\t"
"ldr r8, [%[a], #216]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #216]\n\t"
"# A[55] * B\n\t"
"ldr r8, [%[a], #220]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #220]\n\t"
"# A[56] * B\n\t"
"ldr r8, [%[a], #224]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #224]\n\t"
"# A[57] * B\n\t"
"ldr r8, [%[a], #228]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #228]\n\t"
"# A[58] * B\n\t"
"ldr r8, [%[a], #232]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #232]\n\t"
"# A[59] * B\n\t"
"ldr r8, [%[a], #236]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #236]\n\t"
"# A[60] * B\n\t"
"ldr r8, [%[a], #240]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #240]\n\t"
"# A[61] * B\n\t"
"ldr r8, [%[a], #244]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #244]\n\t"
"# A[62] * B\n\t"
"ldr r8, [%[a], #248]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #248]\n\t"
"# A[63] * B\n\t"
"ldr r8, [%[a], #252]\n\t"
@@ -3666,6 +3561,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -3674,13 +3570,12 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -3688,7 +3583,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -3696,7 +3591,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3705,7 +3600,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3714,7 +3609,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3723,7 +3618,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3732,7 +3627,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3741,7 +3636,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3750,7 +3645,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3759,7 +3654,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3768,7 +3663,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #40]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+11] += m[11] * mu\n\t"
- "ldr r7, [%[m], #44]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
"ldr r9, [%[a], #44]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3777,7 +3672,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #44]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+12] += m[12] * mu\n\t"
- "ldr r7, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #48]\n\t"
"ldr r9, [%[a], #48]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3786,7 +3681,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #48]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+13] += m[13] * mu\n\t"
- "ldr r7, [%[m], #52]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
"ldr r9, [%[a], #52]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3795,7 +3690,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #52]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+14] += m[14] * mu\n\t"
- "ldr r7, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #56]\n\t"
"ldr r9, [%[a], #56]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3804,7 +3699,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #56]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+15] += m[15] * mu\n\t"
- "ldr r7, [%[m], #60]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
"ldr r9, [%[a], #60]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3813,7 +3708,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #60]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+16] += m[16] * mu\n\t"
- "ldr r7, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #64]\n\t"
"ldr r9, [%[a], #64]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3822,7 +3717,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #64]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+17] += m[17] * mu\n\t"
- "ldr r7, [%[m], #68]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
"ldr r9, [%[a], #68]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3831,7 +3726,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #68]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+18] += m[18] * mu\n\t"
- "ldr r7, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #72]\n\t"
"ldr r9, [%[a], #72]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3840,7 +3735,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #72]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+19] += m[19] * mu\n\t"
- "ldr r7, [%[m], #76]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
"ldr r9, [%[a], #76]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3849,7 +3744,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #76]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+20] += m[20] * mu\n\t"
- "ldr r7, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #80]\n\t"
"ldr r9, [%[a], #80]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3858,7 +3753,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #80]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+21] += m[21] * mu\n\t"
- "ldr r7, [%[m], #84]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
"ldr r9, [%[a], #84]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3867,7 +3762,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #84]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+22] += m[22] * mu\n\t"
- "ldr r7, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #88]\n\t"
"ldr r9, [%[a], #88]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3876,7 +3771,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #88]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+23] += m[23] * mu\n\t"
- "ldr r7, [%[m], #92]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
"ldr r9, [%[a], #92]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3885,7 +3780,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #92]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+24] += m[24] * mu\n\t"
- "ldr r7, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #96]\n\t"
"ldr r9, [%[a], #96]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3894,7 +3789,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #96]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+25] += m[25] * mu\n\t"
- "ldr r7, [%[m], #100]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
"ldr r9, [%[a], #100]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3903,7 +3798,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #100]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+26] += m[26] * mu\n\t"
- "ldr r7, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #104]\n\t"
"ldr r9, [%[a], #104]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3912,7 +3807,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #104]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+27] += m[27] * mu\n\t"
- "ldr r7, [%[m], #108]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
"ldr r9, [%[a], #108]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3921,7 +3816,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #108]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+28] += m[28] * mu\n\t"
- "ldr r7, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #112]\n\t"
"ldr r9, [%[a], #112]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3930,7 +3825,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #112]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+29] += m[29] * mu\n\t"
- "ldr r7, [%[m], #116]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
"ldr r9, [%[a], #116]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3939,7 +3834,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #116]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+30] += m[30] * mu\n\t"
- "ldr r7, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #120]\n\t"
"ldr r9, [%[a], #120]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -3970,7 +3865,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
@@ -3985,8 +3880,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_32(r, a, b);
sp_2048_mont_reduce_32(r, m, mp);
@@ -3999,8 +3894,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_32(r, a);
sp_2048_mont_reduce_32(r, m, mp);
@@ -4053,243 +3948,213 @@ static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #44]\n\t"
"# A[12] * B\n\t"
"ldr r8, [%[a], #48]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[13] * B\n\t"
"ldr r8, [%[a], #52]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[14] * B\n\t"
"ldr r8, [%[a], #56]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #56]\n\t"
"# A[15] * B\n\t"
"ldr r8, [%[a], #60]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #60]\n\t"
"# A[16] * B\n\t"
"ldr r8, [%[a], #64]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #64]\n\t"
"# A[17] * B\n\t"
"ldr r8, [%[a], #68]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #68]\n\t"
"# A[18] * B\n\t"
"ldr r8, [%[a], #72]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #72]\n\t"
"# A[19] * B\n\t"
"ldr r8, [%[a], #76]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #76]\n\t"
"# A[20] * B\n\t"
"ldr r8, [%[a], #80]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[21] * B\n\t"
"ldr r8, [%[a], #84]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[22] * B\n\t"
"ldr r8, [%[a], #88]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #88]\n\t"
"# A[23] * B\n\t"
"ldr r8, [%[a], #92]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #92]\n\t"
"# A[24] * B\n\t"
"ldr r8, [%[a], #96]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #96]\n\t"
"# A[25] * B\n\t"
"ldr r8, [%[a], #100]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #100]\n\t"
"# A[26] * B\n\t"
"ldr r8, [%[a], #104]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #104]\n\t"
"# A[27] * B\n\t"
"ldr r8, [%[a], #108]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #108]\n\t"
"# A[28] * B\n\t"
"ldr r8, [%[a], #112]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #112]\n\t"
"# A[29] * B\n\t"
"ldr r8, [%[a], #116]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #116]\n\t"
"# A[30] * B\n\t"
"ldr r8, [%[a], #120]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #120]\n\t"
"# A[31] * B\n\t"
"ldr r8, [%[a], #124]\n\t"
@@ -4846,7 +4711,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4912,34 +4778,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -4991,7 +4857,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5073,34 +4940,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -5131,7 +4998,7 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -5148,7 +5015,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m)
sp_2048_sub_in_place_64(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -5527,6 +5394,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -5535,13 +5403,12 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -5549,7 +5416,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -5557,7 +5424,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5566,7 +5433,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5575,7 +5442,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5584,7 +5451,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5593,7 +5460,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5602,7 +5469,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5611,7 +5478,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5620,7 +5487,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5629,7 +5496,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #40]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+11] += m[11] * mu\n\t"
- "ldr r7, [%[m], #44]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
"ldr r9, [%[a], #44]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5638,7 +5505,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #44]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+12] += m[12] * mu\n\t"
- "ldr r7, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #48]\n\t"
"ldr r9, [%[a], #48]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5647,7 +5514,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #48]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+13] += m[13] * mu\n\t"
- "ldr r7, [%[m], #52]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
"ldr r9, [%[a], #52]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5656,7 +5523,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #52]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+14] += m[14] * mu\n\t"
- "ldr r7, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #56]\n\t"
"ldr r9, [%[a], #56]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5665,7 +5532,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #56]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+15] += m[15] * mu\n\t"
- "ldr r7, [%[m], #60]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
"ldr r9, [%[a], #60]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5674,7 +5541,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #60]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+16] += m[16] * mu\n\t"
- "ldr r7, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #64]\n\t"
"ldr r9, [%[a], #64]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5683,7 +5550,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #64]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+17] += m[17] * mu\n\t"
- "ldr r7, [%[m], #68]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
"ldr r9, [%[a], #68]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5692,7 +5559,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #68]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+18] += m[18] * mu\n\t"
- "ldr r7, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #72]\n\t"
"ldr r9, [%[a], #72]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5701,7 +5568,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #72]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+19] += m[19] * mu\n\t"
- "ldr r7, [%[m], #76]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
"ldr r9, [%[a], #76]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5710,7 +5577,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #76]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+20] += m[20] * mu\n\t"
- "ldr r7, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #80]\n\t"
"ldr r9, [%[a], #80]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5719,7 +5586,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #80]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+21] += m[21] * mu\n\t"
- "ldr r7, [%[m], #84]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
"ldr r9, [%[a], #84]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5728,7 +5595,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #84]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+22] += m[22] * mu\n\t"
- "ldr r7, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #88]\n\t"
"ldr r9, [%[a], #88]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5737,7 +5604,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #88]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+23] += m[23] * mu\n\t"
- "ldr r7, [%[m], #92]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
"ldr r9, [%[a], #92]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5746,7 +5613,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #92]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+24] += m[24] * mu\n\t"
- "ldr r7, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #96]\n\t"
"ldr r9, [%[a], #96]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5755,7 +5622,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #96]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+25] += m[25] * mu\n\t"
- "ldr r7, [%[m], #100]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
"ldr r9, [%[a], #100]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5764,7 +5631,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #100]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+26] += m[26] * mu\n\t"
- "ldr r7, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #104]\n\t"
"ldr r9, [%[a], #104]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5773,7 +5640,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #104]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+27] += m[27] * mu\n\t"
- "ldr r7, [%[m], #108]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
"ldr r9, [%[a], #108]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5782,7 +5649,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #108]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+28] += m[28] * mu\n\t"
- "ldr r7, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #112]\n\t"
"ldr r9, [%[a], #112]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5791,7 +5658,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #112]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+29] += m[29] * mu\n\t"
- "ldr r7, [%[m], #116]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
"ldr r9, [%[a], #116]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5800,7 +5667,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #116]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+30] += m[30] * mu\n\t"
- "ldr r7, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #120]\n\t"
"ldr r9, [%[a], #120]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5809,7 +5676,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #120]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+31] += m[31] * mu\n\t"
- "ldr r7, [%[m], #124]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
"ldr r9, [%[a], #124]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5818,7 +5685,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #124]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+32] += m[32] * mu\n\t"
- "ldr r7, [%[m], #128]\n\t"
+ "ldr r7, [%[m], #128]\n\t"
"ldr r9, [%[a], #128]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5827,7 +5694,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #128]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+33] += m[33] * mu\n\t"
- "ldr r7, [%[m], #132]\n\t"
+ "ldr r7, [%[m], #132]\n\t"
"ldr r9, [%[a], #132]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5836,7 +5703,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #132]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+34] += m[34] * mu\n\t"
- "ldr r7, [%[m], #136]\n\t"
+ "ldr r7, [%[m], #136]\n\t"
"ldr r9, [%[a], #136]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5845,7 +5712,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #136]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+35] += m[35] * mu\n\t"
- "ldr r7, [%[m], #140]\n\t"
+ "ldr r7, [%[m], #140]\n\t"
"ldr r9, [%[a], #140]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5854,7 +5721,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #140]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+36] += m[36] * mu\n\t"
- "ldr r7, [%[m], #144]\n\t"
+ "ldr r7, [%[m], #144]\n\t"
"ldr r9, [%[a], #144]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5863,7 +5730,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #144]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+37] += m[37] * mu\n\t"
- "ldr r7, [%[m], #148]\n\t"
+ "ldr r7, [%[m], #148]\n\t"
"ldr r9, [%[a], #148]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5872,7 +5739,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #148]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+38] += m[38] * mu\n\t"
- "ldr r7, [%[m], #152]\n\t"
+ "ldr r7, [%[m], #152]\n\t"
"ldr r9, [%[a], #152]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5881,7 +5748,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #152]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+39] += m[39] * mu\n\t"
- "ldr r7, [%[m], #156]\n\t"
+ "ldr r7, [%[m], #156]\n\t"
"ldr r9, [%[a], #156]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5890,7 +5757,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #156]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+40] += m[40] * mu\n\t"
- "ldr r7, [%[m], #160]\n\t"
+ "ldr r7, [%[m], #160]\n\t"
"ldr r9, [%[a], #160]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5899,7 +5766,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #160]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+41] += m[41] * mu\n\t"
- "ldr r7, [%[m], #164]\n\t"
+ "ldr r7, [%[m], #164]\n\t"
"ldr r9, [%[a], #164]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5908,7 +5775,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #164]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+42] += m[42] * mu\n\t"
- "ldr r7, [%[m], #168]\n\t"
+ "ldr r7, [%[m], #168]\n\t"
"ldr r9, [%[a], #168]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5917,7 +5784,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #168]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+43] += m[43] * mu\n\t"
- "ldr r7, [%[m], #172]\n\t"
+ "ldr r7, [%[m], #172]\n\t"
"ldr r9, [%[a], #172]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5926,7 +5793,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #172]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+44] += m[44] * mu\n\t"
- "ldr r7, [%[m], #176]\n\t"
+ "ldr r7, [%[m], #176]\n\t"
"ldr r9, [%[a], #176]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5935,7 +5802,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #176]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+45] += m[45] * mu\n\t"
- "ldr r7, [%[m], #180]\n\t"
+ "ldr r7, [%[m], #180]\n\t"
"ldr r9, [%[a], #180]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5944,7 +5811,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #180]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+46] += m[46] * mu\n\t"
- "ldr r7, [%[m], #184]\n\t"
+ "ldr r7, [%[m], #184]\n\t"
"ldr r9, [%[a], #184]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5953,7 +5820,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #184]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+47] += m[47] * mu\n\t"
- "ldr r7, [%[m], #188]\n\t"
+ "ldr r7, [%[m], #188]\n\t"
"ldr r9, [%[a], #188]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5962,7 +5829,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #188]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+48] += m[48] * mu\n\t"
- "ldr r7, [%[m], #192]\n\t"
+ "ldr r7, [%[m], #192]\n\t"
"ldr r9, [%[a], #192]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5971,7 +5838,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #192]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+49] += m[49] * mu\n\t"
- "ldr r7, [%[m], #196]\n\t"
+ "ldr r7, [%[m], #196]\n\t"
"ldr r9, [%[a], #196]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5980,7 +5847,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #196]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+50] += m[50] * mu\n\t"
- "ldr r7, [%[m], #200]\n\t"
+ "ldr r7, [%[m], #200]\n\t"
"ldr r9, [%[a], #200]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5989,7 +5856,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #200]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+51] += m[51] * mu\n\t"
- "ldr r7, [%[m], #204]\n\t"
+ "ldr r7, [%[m], #204]\n\t"
"ldr r9, [%[a], #204]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -5998,7 +5865,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #204]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+52] += m[52] * mu\n\t"
- "ldr r7, [%[m], #208]\n\t"
+ "ldr r7, [%[m], #208]\n\t"
"ldr r9, [%[a], #208]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6007,7 +5874,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #208]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+53] += m[53] * mu\n\t"
- "ldr r7, [%[m], #212]\n\t"
+ "ldr r7, [%[m], #212]\n\t"
"ldr r9, [%[a], #212]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6016,7 +5883,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #212]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+54] += m[54] * mu\n\t"
- "ldr r7, [%[m], #216]\n\t"
+ "ldr r7, [%[m], #216]\n\t"
"ldr r9, [%[a], #216]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6025,7 +5892,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #216]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+55] += m[55] * mu\n\t"
- "ldr r7, [%[m], #220]\n\t"
+ "ldr r7, [%[m], #220]\n\t"
"ldr r9, [%[a], #220]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6034,7 +5901,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #220]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+56] += m[56] * mu\n\t"
- "ldr r7, [%[m], #224]\n\t"
+ "ldr r7, [%[m], #224]\n\t"
"ldr r9, [%[a], #224]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6043,7 +5910,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #224]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+57] += m[57] * mu\n\t"
- "ldr r7, [%[m], #228]\n\t"
+ "ldr r7, [%[m], #228]\n\t"
"ldr r9, [%[a], #228]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6052,7 +5919,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #228]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+58] += m[58] * mu\n\t"
- "ldr r7, [%[m], #232]\n\t"
+ "ldr r7, [%[m], #232]\n\t"
"ldr r9, [%[a], #232]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6061,7 +5928,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #232]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+59] += m[59] * mu\n\t"
- "ldr r7, [%[m], #236]\n\t"
+ "ldr r7, [%[m], #236]\n\t"
"ldr r9, [%[a], #236]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6070,7 +5937,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #236]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+60] += m[60] * mu\n\t"
- "ldr r7, [%[m], #240]\n\t"
+ "ldr r7, [%[m], #240]\n\t"
"ldr r9, [%[a], #240]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6079,7 +5946,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #240]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+61] += m[61] * mu\n\t"
- "ldr r7, [%[m], #244]\n\t"
+ "ldr r7, [%[m], #244]\n\t"
"ldr r9, [%[a], #244]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6088,7 +5955,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #244]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+62] += m[62] * mu\n\t"
- "ldr r7, [%[m], #248]\n\t"
+ "ldr r7, [%[m], #248]\n\t"
"ldr r9, [%[a], #248]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -6119,7 +5986,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca);
@@ -6134,8 +6001,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_64(r, a, b);
sp_2048_mont_reduce_64(r, m, mp);
@@ -6148,8 +6015,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_64(r, a);
sp_2048_mont_reduce_64(r, m, mp);
@@ -7135,7 +7002,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7201,34 +7069,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -7280,7 +7148,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7362,34 +7231,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -7434,11 +7303,13 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[128], m[64], r[128];
+ sp_digit a[128];
+ sp_digit m[64];
+ sp_digit r[128];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -7781,9 +7652,9 @@ static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -7847,8 +7718,11 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[64 * 2];
- sp_digit p[32], q[32], dp[32];
- sp_digit tmpa[64], tmpb[64];
+ sp_digit p[32];
+ sp_digit q[32];
+ sp_digit dp[32];
+ sp_digit tmpa[64];
+ sp_digit tmpb[64];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -7945,7 +7819,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -7968,17 +7842,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 64;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -7991,14 +7867,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -8025,10 +7903,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -8479,10 +8360,12 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -8517,34 +8400,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_2048_lshift_64(r, norm, (byte)y);
+ sp_2048_lshift_64(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -8555,7 +8438,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_2048_mont_sqr_64(r, r, m, mp);
sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_lshift_64(r, r, (byte)y);
+ sp_2048_lshift_64(r, r, y);
sp_2048_mul_d_64(tmp, norm, r[64]);
r[64] = 0;
o = sp_2048_add_64(r, r, tmp);
@@ -8591,11 +8474,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
word32 i;
@@ -8630,6 +8515,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -8651,10 +8537,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -8691,7 +8580,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -8705,7 +8594,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8747,7 +8637,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8781,7 +8672,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -8820,7 +8713,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 3072 / 8 - 1;
a[j] = 0;
@@ -8862,66 +8758,60 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"sub sp, sp, #48\n\t"
"mov r10, #0\n\t"
"# A[0] * B[0]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r3, r4, r8, r9\n\t"
+ "ldr r11, [%[a], #0]\n\t"
+ "ldr r12, [%[b], #0]\n\t"
+ "umull r3, r4, r11, r12\n\t"
"mov r5, #0\n\t"
"str r3, [sp]\n\t"
"# A[0] * B[1]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[1] * B[0]\n\t"
"ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #4]\n\t"
+ "# A[2] * B[0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[1]\n\t"
+ "ldr r11, [%[a], #4]\n\t"
+ "ldr r12, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[0] * B[2]\n\t"
"ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[1] * B[1]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[0]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #8]\n\t"
"# A[0] * B[3]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
"# A[1] * B[2]\n\t"
- "ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[2] * B[1]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -8933,13 +8823,25 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #12]\n\t"
- "# A[0] * B[4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[4] * B[0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
+ "# A[3] * B[1]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[2]\n\t"
+ "ldr r11, [%[a], #8]\n\t"
+ "ldr r12, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[1] * B[3]\n\t"
"ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #12]\n\t"
@@ -8947,30 +8849,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[2] * B[2]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[1]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[0]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #16]\n\t"
"# A[0] * B[5]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
@@ -8984,16 +8871,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[2] * B[3]\n\t"
- "ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[3] * B[2]\n\t"
"ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -9012,20 +8897,32 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #20]\n\t"
- "# A[0] * B[6]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[6] * B[0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
- "# A[1] * B[5]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #20]\n\t"
+ "# A[5] * B[1]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
+ "# A[4] * B[2]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[3]\n\t"
+ "ldr r11, [%[a], #12]\n\t"
+ "ldr r12, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[2] * B[4]\n\t"
"ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #16]\n\t"
@@ -9033,37 +8930,22 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[3] * B[3]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[1] * B[5]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[4] * B[2]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[1]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[0]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[6]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #24]\n\t"
"# A[0] * B[7]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
@@ -9084,16 +8966,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[3] * B[4]\n\t"
- "ldr r8, [%[a], #12]\n\t"
"ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[4] * B[3]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -9119,44 +8999,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #28]\n\t"
- "# A[0] * B[8]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #32]\n\t"
+ "# A[8] * B[0]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
- "# A[1] * B[7]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[6]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[3] * B[5]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[4] * B[4]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[3]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[7] * B[1]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -9168,23 +9019,49 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[7] * B[1]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[5] * B[3]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[4]\n\t"
+ "ldr r11, [%[a], #16]\n\t"
+ "ldr r12, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[5]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[8] * B[0]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[2] * B[6]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[1] * B[7]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #32]\n\t"
"# A[0] * B[9]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #36]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
@@ -9212,16 +9089,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[4] * B[5]\n\t"
- "ldr r8, [%[a], #16]\n\t"
"ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[5] * B[4]\n\t"
"ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -9254,58 +9129,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #36]\n\t"
- "# A[0] * B[10]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #40]\n\t"
+ "# A[10] * B[0]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
- "# A[1] * B[9]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[2] * B[8]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[7]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[6]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[5] * B[5]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[6] * B[4]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[7] * B[3]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[9] * B[1]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -9317,23 +9149,63 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[9] * B[1]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[7] * B[3]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[10] * B[0]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[6] * B[4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[5]\n\t"
+ "ldr r11, [%[a], #20]\n\t"
+ "ldr r12, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[6]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[7]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[8]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[9]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[0] * B[10]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #40]\n\t"
"# A[0] * B[11]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
@@ -9368,16 +9240,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[5] * B[6]\n\t"
- "ldr r8, [%[a], #20]\n\t"
"ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[6] * B[5]\n\t"
"ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -9417,58 +9287,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #44]\n\t"
- "# A[1] * B[11]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
- "# A[2] * B[10]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[3] * B[9]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[4] * B[8]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[7]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[6]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[7] * B[5]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[8] * B[4]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[10] * B[2]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -9480,16 +9307,57 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[10] * B[2]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #8]\n\t"
+ "# A[8] * B[4]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[11] * B[1]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[7] * B[5]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[6]\n\t"
+ "ldr r11, [%[a], #24]\n\t"
+ "ldr r12, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[7]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[8]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[9]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[10]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[1] * B[11]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -9497,7 +9365,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r3, [%[r], #48]\n\t"
"# A[2] * B[11]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -9524,16 +9391,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[6] * B[7]\n\t"
- "ldr r8, [%[a], #24]\n\t"
"ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[7] * B[6]\n\t"
"ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -9566,44 +9431,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [%[r], #52]\n\t"
- "# A[3] * B[11]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
- "# A[4] * B[10]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[9]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[6] * B[8]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[7] * B[7]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[8] * B[6]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[10] * B[4]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -9615,16 +9451,43 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[10] * B[4]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[8] * B[6]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[7]\n\t"
+ "ldr r11, [%[a], #28]\n\t"
+ "ldr r12, [%[b], #28]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[8]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[11] * B[3]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[5] * B[9]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[10]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[11]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -9632,7 +9495,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r5, [%[r], #56]\n\t"
"# A[4] * B[11]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -9652,16 +9514,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[7] * B[8]\n\t"
- "ldr r8, [%[a], #28]\n\t"
"ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[8] * B[7]\n\t"
"ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -9687,20 +9547,32 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #60]\n\t"
- "# A[5] * B[11]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
- "# A[6] * B[10]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #40]\n\t"
+ "# A[10] * B[6]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
+ "# A[9] * B[7]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[8]\n\t"
+ "ldr r11, [%[a], #32]\n\t"
+ "ldr r12, [%[b], #32]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[7] * B[9]\n\t"
"ldr r8, [%[a], #28]\n\t"
"ldr r9, [%[b], #36]\n\t"
@@ -9708,30 +9580,16 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[8] * B[8]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #32]\n\t"
+ "# A[6] * B[10]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[9] * B[7]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[10] * B[6]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[11] * B[5]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #20]\n\t"
+ "# A[5] * B[11]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -9739,7 +9597,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r4, [%[r], #64]\n\t"
"# A[6] * B[11]\n\t"
"ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -9752,16 +9609,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[8] * B[9]\n\t"
- "ldr r8, [%[a], #32]\n\t"
"ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[9] * B[8]\n\t"
"ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -9780,13 +9635,25 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [%[r], #68]\n\t"
- "# A[7] * B[11]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
+ "# A[10] * B[8]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[9]\n\t"
+ "ldr r11, [%[a], #36]\n\t"
+ "ldr r12, [%[b], #36]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[8] * B[10]\n\t"
"ldr r8, [%[a], #32]\n\t"
"ldr r9, [%[b], #40]\n\t"
@@ -9794,23 +9661,9 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[9] * B[9]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[10] * B[8]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[11] * B[7]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #28]\n\t"
+ "# A[7] * B[11]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -9818,22 +9671,19 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r3, [%[r], #72]\n\t"
"# A[8] * B[11]\n\t"
"ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[9] * B[10]\n\t"
- "ldr r8, [%[a], #36]\n\t"
"ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[10] * B[9]\n\t"
"ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -9845,79 +9695,54 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [%[r], #76]\n\t"
+ "# A[11] * B[9]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[10] * B[10]\n\t"
+ "ldr r11, [%[a], #40]\n\t"
+ "ldr r12, [%[b], #40]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[9] * B[11]\n\t"
"ldr r8, [%[a], #36]\n\t"
"ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[10] * B[10]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[11] * B[9]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[10] * B[11]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #44]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
"# A[11] * B[10]\n\t"
"ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[11] * B[11]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adc r5, r5, r7\n\t"
"str r4, [%[r], #88]\n\t"
"str r5, [%[r], #92]\n\t"
- "ldr r3, [sp, #0]\n\t"
- "ldr r4, [sp, #4]\n\t"
- "ldr r5, [sp, #8]\n\t"
- "ldr r6, [sp, #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [sp, #16]\n\t"
- "ldr r4, [sp, #20]\n\t"
- "ldr r5, [sp, #24]\n\t"
- "ldr r6, [sp, #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "ldr r3, [sp, #32]\n\t"
- "ldr r4, [sp, #36]\n\t"
- "ldr r5, [sp, #40]\n\t"
- "ldr r6, [sp, #44]\n\t"
- "str r3, [%[r], #32]\n\t"
- "str r4, [%[r], #36]\n\t"
- "str r5, [%[r], #40]\n\t"
- "str r6, [%[r], #44]\n\t"
- "add sp, sp, #48\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "sub %[r], %[r], #48\n\t"
:
: [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@@ -9930,7 +9755,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
{
__asm__ __volatile__ (
"sub sp, sp, #48\n\t"
- "mov r14, #0\n\t"
+ "mov r12, #0\n\t"
"# A[0] * A[0]\n\t"
"ldr r10, [%[a], #0]\n\t"
"umull r8, r3, r10, r10\n\t"
@@ -9942,10 +9767,10 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [sp, #4]\n\t"
"# A[0] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
@@ -9953,16 +9778,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
+ "adc r3, r12, r12\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"# A[1] * A[1]\n\t"
"ldr r10, [%[a], #4]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"str r4, [sp, #8]\n\t"
"# A[0] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
@@ -9970,20 +9795,20 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
+ "adc r4, r12, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"# A[1] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
"ldr r8, [%[a], #4]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"str r2, [sp, #12]\n\t"
"# A[0] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
@@ -9991,26 +9816,26 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[1] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"ldr r8, [%[a], #4]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[2] * A[2]\n\t"
"ldr r10, [%[a], #8]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [sp, #16]\n\t"
"# A[0] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
@@ -10024,14 +9849,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10051,14 +9876,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[3]\n\t"
"ldr r10, [%[a], #12]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10067,7 +9892,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r2, r2, r5\n\t"
"adcs r3, r3, r6\n\t"
"adc r4, r4, r7\n\t"
@@ -10084,21 +9909,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10118,21 +9943,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[4]\n\t"
"ldr r10, [%[a], #16]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10141,7 +9966,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r4, r4, r5\n\t"
"adcs r2, r2, r6\n\t"
"adc r3, r3, r7\n\t"
@@ -10158,28 +9983,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10199,28 +10024,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[5] * A[5]\n\t"
"ldr r10, [%[a], #20]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10229,7 +10054,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r3, r3, r5\n\t"
"adcs r4, r4, r6\n\t"
"adc r2, r2, r7\n\t"
@@ -10246,35 +10071,35 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[2] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #8]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[5] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"ldr r8, [%[a], #20]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10294,28 +10119,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[3] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #12]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[5] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"ldr r8, [%[a], #20]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[6] * A[6]\n\t"
"ldr r10, [%[a], #24]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10324,7 +10149,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r2, r2, r5\n\t"
"adcs r3, r3, r6\n\t"
"adc r4, r4, r7\n\t"
@@ -10341,28 +10166,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[4] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #16]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[5] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #20]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[6] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"ldr r8, [%[a], #24]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10382,21 +10207,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[5] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #20]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[6] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #24]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[7] * A[7]\n\t"
"ldr r10, [%[a], #28]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10405,7 +10230,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r4, r4, r5\n\t"
"adcs r2, r2, r6\n\t"
"adc r3, r3, r7\n\t"
@@ -10422,21 +10247,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[6] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #24]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[7] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"ldr r8, [%[a], #28]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10456,14 +10281,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[7] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #28]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[8] * A[8]\n\t"
"ldr r10, [%[a], #32]\n\t"
"umull r8, r9, r10, r10\n\t"
@@ -10472,7 +10297,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r7, r7, r7\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r3, r3, r5\n\t"
"adcs r4, r4, r6\n\t"
"adc r2, r2, r7\n\t"
@@ -10489,14 +10314,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"# A[8] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"ldr r8, [%[a], #32]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r5, r5, r8\n\t"
"adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
+ "adc r7, r7, r12\n\t"
"adds r5, r5, r5\n\t"
"adcs r6, r6, r6\n\t"
"adc r7, r7, r7\n\t"
@@ -10510,26 +10335,26 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
+ "adc r4, r12, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"# A[8] * A[10]\n\t"
"ldr r10, [%[a], #40]\n\t"
"ldr r8, [%[a], #32]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"# A[9] * A[9]\n\t"
"ldr r10, [%[a], #36]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"str r2, [%[r], #72]\n\t"
"# A[8] * A[11]\n\t"
"ldr r10, [%[a], #44]\n\t"
@@ -10537,20 +10362,20 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
+ "adc r2, r12, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"# A[9] * A[10]\n\t"
"ldr r10, [%[a], #40]\n\t"
"ldr r8, [%[a], #36]\n\t"
"umull r8, r9, r10, r8\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"adds r3, r3, r8\n\t"
"adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
+ "adc r2, r2, r12\n\t"
"str r3, [%[r], #76]\n\t"
"# A[9] * A[11]\n\t"
"ldr r10, [%[a], #44]\n\t"
@@ -10558,16 +10383,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
+ "adc r3, r12, r12\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"# A[10] * A[10]\n\t"
"ldr r10, [%[a], #40]\n\t"
"umull r8, r9, r10, r10\n\t"
"adds r4, r4, r8\n\t"
"adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
+ "adc r3, r3, r12\n\t"
"str r4, [%[r], #80]\n\t"
"# A[10] * A[11]\n\t"
"ldr r10, [%[a], #44]\n\t"
@@ -10575,10 +10400,10 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"umull r8, r9, r10, r8\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
+ "adc r4, r12, r12\n\t"
"adds r2, r2, r8\n\t"
"adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
+ "adc r4, r4, r12\n\t"
"str r2, [%[r], #84]\n\t"
"# A[11] * A[11]\n\t"
"ldr r10, [%[a], #44]\n\t"
@@ -10587,34 +10412,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
"adc r4, r4, r9\n\t"
"str r3, [%[r], #88]\n\t"
"str r4, [%[r], #92]\n\t"
- "ldr r2, [sp, #0]\n\t"
- "ldr r3, [sp, #4]\n\t"
- "ldr r4, [sp, #8]\n\t"
- "ldr r8, [sp, #12]\n\t"
- "str r2, [%[r], #0]\n\t"
- "str r3, [%[r], #4]\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r8, [%[r], #12]\n\t"
- "ldr r2, [sp, #16]\n\t"
- "ldr r3, [sp, #20]\n\t"
- "ldr r4, [sp, #24]\n\t"
- "ldr r8, [sp, #28]\n\t"
- "str r2, [%[r], #16]\n\t"
- "str r3, [%[r], #20]\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r8, [%[r], #28]\n\t"
- "ldr r2, [sp, #32]\n\t"
- "ldr r3, [sp, #36]\n\t"
- "ldr r4, [sp, #40]\n\t"
- "ldr r8, [sp, #44]\n\t"
- "str r2, [%[r], #32]\n\t"
- "str r3, [%[r], #36]\n\t"
- "str r4, [%[r], #40]\n\t"
- "str r8, [%[r], #44]\n\t"
- "add sp, sp, #48\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "sub %[r], %[r], #48\n\t"
:
: [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
+ : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12"
);
}
@@ -10965,7 +10772,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
sp_digit a1[12];
sp_digit b1[12];
sp_digit z2[24];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_12(a1, a, &a[12]);
cb = sp_3072_add_12(b1, b, &b[12]);
@@ -11480,7 +11289,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
sp_digit a1[24];
sp_digit b1[24];
sp_digit z2[48];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_24(a1, a, &a[24]);
cb = sp_3072_add_24(b1, b, &b[24]);
@@ -12379,7 +12190,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
sp_digit a1[48];
sp_digit b1[48];
sp_digit z2[96];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_48(a1, a, &a[48]);
cb = sp_3072_add_48(b1, b, &b[48]);
@@ -12894,7 +12707,7 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -12903,7 +12716,8 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -12912,7 +12726,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -12962,755 +12776,661 @@ static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #44]\n\t"
"# A[12] * B\n\t"
"ldr r8, [%[a], #48]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[13] * B\n\t"
"ldr r8, [%[a], #52]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[14] * B\n\t"
"ldr r8, [%[a], #56]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #56]\n\t"
"# A[15] * B\n\t"
"ldr r8, [%[a], #60]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #60]\n\t"
"# A[16] * B\n\t"
"ldr r8, [%[a], #64]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #64]\n\t"
"# A[17] * B\n\t"
"ldr r8, [%[a], #68]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #68]\n\t"
"# A[18] * B\n\t"
"ldr r8, [%[a], #72]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #72]\n\t"
"# A[19] * B\n\t"
"ldr r8, [%[a], #76]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #76]\n\t"
"# A[20] * B\n\t"
"ldr r8, [%[a], #80]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[21] * B\n\t"
"ldr r8, [%[a], #84]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[22] * B\n\t"
"ldr r8, [%[a], #88]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #88]\n\t"
"# A[23] * B\n\t"
"ldr r8, [%[a], #92]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #92]\n\t"
"# A[24] * B\n\t"
"ldr r8, [%[a], #96]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #96]\n\t"
"# A[25] * B\n\t"
"ldr r8, [%[a], #100]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #100]\n\t"
"# A[26] * B\n\t"
"ldr r8, [%[a], #104]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #104]\n\t"
"# A[27] * B\n\t"
"ldr r8, [%[a], #108]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #108]\n\t"
"# A[28] * B\n\t"
"ldr r8, [%[a], #112]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #112]\n\t"
"# A[29] * B\n\t"
"ldr r8, [%[a], #116]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #116]\n\t"
"# A[30] * B\n\t"
"ldr r8, [%[a], #120]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #120]\n\t"
"# A[31] * B\n\t"
"ldr r8, [%[a], #124]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #124]\n\t"
"# A[32] * B\n\t"
"ldr r8, [%[a], #128]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #128]\n\t"
"# A[33] * B\n\t"
"ldr r8, [%[a], #132]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #132]\n\t"
"# A[34] * B\n\t"
"ldr r8, [%[a], #136]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #136]\n\t"
"# A[35] * B\n\t"
"ldr r8, [%[a], #140]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #140]\n\t"
"# A[36] * B\n\t"
"ldr r8, [%[a], #144]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #144]\n\t"
"# A[37] * B\n\t"
"ldr r8, [%[a], #148]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #148]\n\t"
"# A[38] * B\n\t"
"ldr r8, [%[a], #152]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #152]\n\t"
"# A[39] * B\n\t"
"ldr r8, [%[a], #156]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #156]\n\t"
"# A[40] * B\n\t"
"ldr r8, [%[a], #160]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #160]\n\t"
"# A[41] * B\n\t"
"ldr r8, [%[a], #164]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #164]\n\t"
"# A[42] * B\n\t"
"ldr r8, [%[a], #168]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #168]\n\t"
"# A[43] * B\n\t"
"ldr r8, [%[a], #172]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #172]\n\t"
"# A[44] * B\n\t"
"ldr r8, [%[a], #176]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #176]\n\t"
"# A[45] * B\n\t"
"ldr r8, [%[a], #180]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #180]\n\t"
"# A[46] * B\n\t"
"ldr r8, [%[a], #184]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #184]\n\t"
"# A[47] * B\n\t"
"ldr r8, [%[a], #188]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #188]\n\t"
"# A[48] * B\n\t"
"ldr r8, [%[a], #192]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #192]\n\t"
"# A[49] * B\n\t"
"ldr r8, [%[a], #196]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #196]\n\t"
"# A[50] * B\n\t"
"ldr r8, [%[a], #200]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #200]\n\t"
"# A[51] * B\n\t"
"ldr r8, [%[a], #204]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #204]\n\t"
"# A[52] * B\n\t"
"ldr r8, [%[a], #208]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #208]\n\t"
"# A[53] * B\n\t"
"ldr r8, [%[a], #212]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #212]\n\t"
"# A[54] * B\n\t"
"ldr r8, [%[a], #216]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #216]\n\t"
"# A[55] * B\n\t"
"ldr r8, [%[a], #220]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #220]\n\t"
"# A[56] * B\n\t"
"ldr r8, [%[a], #224]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #224]\n\t"
"# A[57] * B\n\t"
"ldr r8, [%[a], #228]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #228]\n\t"
"# A[58] * B\n\t"
"ldr r8, [%[a], #232]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #232]\n\t"
"# A[59] * B\n\t"
"ldr r8, [%[a], #236]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #236]\n\t"
"# A[60] * B\n\t"
"ldr r8, [%[a], #240]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #240]\n\t"
"# A[61] * B\n\t"
"ldr r8, [%[a], #244]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #244]\n\t"
"# A[62] * B\n\t"
"ldr r8, [%[a], #248]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #248]\n\t"
"# A[63] * B\n\t"
"ldr r8, [%[a], #252]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #252]\n\t"
"# A[64] * B\n\t"
"ldr r8, [%[a], #256]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #256]\n\t"
"# A[65] * B\n\t"
"ldr r8, [%[a], #260]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #260]\n\t"
"# A[66] * B\n\t"
"ldr r8, [%[a], #264]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #264]\n\t"
"# A[67] * B\n\t"
"ldr r8, [%[a], #268]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #268]\n\t"
"# A[68] * B\n\t"
"ldr r8, [%[a], #272]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #272]\n\t"
"# A[69] * B\n\t"
"ldr r8, [%[a], #276]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #276]\n\t"
"# A[70] * B\n\t"
"ldr r8, [%[a], #280]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #280]\n\t"
"# A[71] * B\n\t"
"ldr r8, [%[a], #284]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #284]\n\t"
"# A[72] * B\n\t"
"ldr r8, [%[a], #288]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #288]\n\t"
"# A[73] * B\n\t"
"ldr r8, [%[a], #292]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #292]\n\t"
"# A[74] * B\n\t"
"ldr r8, [%[a], #296]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #296]\n\t"
"# A[75] * B\n\t"
"ldr r8, [%[a], #300]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #300]\n\t"
"# A[76] * B\n\t"
"ldr r8, [%[a], #304]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #304]\n\t"
"# A[77] * B\n\t"
"ldr r8, [%[a], #308]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #308]\n\t"
"# A[78] * B\n\t"
"ldr r8, [%[a], #312]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #312]\n\t"
"# A[79] * B\n\t"
"ldr r8, [%[a], #316]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #316]\n\t"
"# A[80] * B\n\t"
"ldr r8, [%[a], #320]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #320]\n\t"
"# A[81] * B\n\t"
"ldr r8, [%[a], #324]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #324]\n\t"
"# A[82] * B\n\t"
"ldr r8, [%[a], #328]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #328]\n\t"
"# A[83] * B\n\t"
"ldr r8, [%[a], #332]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #332]\n\t"
"# A[84] * B\n\t"
"ldr r8, [%[a], #336]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #336]\n\t"
"# A[85] * B\n\t"
"ldr r8, [%[a], #340]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #340]\n\t"
"# A[86] * B\n\t"
"ldr r8, [%[a], #344]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #344]\n\t"
"# A[87] * B\n\t"
"ldr r8, [%[a], #348]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #348]\n\t"
"# A[88] * B\n\t"
"ldr r8, [%[a], #352]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #352]\n\t"
"# A[89] * B\n\t"
"ldr r8, [%[a], #356]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #356]\n\t"
"# A[90] * B\n\t"
"ldr r8, [%[a], #360]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #360]\n\t"
"# A[91] * B\n\t"
"ldr r8, [%[a], #364]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #364]\n\t"
"# A[92] * B\n\t"
"ldr r8, [%[a], #368]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #368]\n\t"
"# A[93] * B\n\t"
"ldr r8, [%[a], #372]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #372]\n\t"
"# A[94] * B\n\t"
"ldr r8, [%[a], #376]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #376]\n\t"
"# A[95] * B\n\t"
"ldr r8, [%[a], #380]\n\t"
@@ -14039,6 +13759,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -14047,13 +13768,12 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -14061,7 +13781,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -14069,7 +13789,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14078,7 +13798,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14087,7 +13807,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14096,7 +13816,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14105,7 +13825,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14114,7 +13834,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14123,7 +13843,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14132,7 +13852,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14141,7 +13861,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #40]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+11] += m[11] * mu\n\t"
- "ldr r7, [%[m], #44]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
"ldr r9, [%[a], #44]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14150,7 +13870,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #44]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+12] += m[12] * mu\n\t"
- "ldr r7, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #48]\n\t"
"ldr r9, [%[a], #48]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14159,7 +13879,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #48]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+13] += m[13] * mu\n\t"
- "ldr r7, [%[m], #52]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
"ldr r9, [%[a], #52]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14168,7 +13888,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #52]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+14] += m[14] * mu\n\t"
- "ldr r7, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #56]\n\t"
"ldr r9, [%[a], #56]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14177,7 +13897,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #56]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+15] += m[15] * mu\n\t"
- "ldr r7, [%[m], #60]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
"ldr r9, [%[a], #60]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14186,7 +13906,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #60]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+16] += m[16] * mu\n\t"
- "ldr r7, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #64]\n\t"
"ldr r9, [%[a], #64]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14195,7 +13915,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #64]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+17] += m[17] * mu\n\t"
- "ldr r7, [%[m], #68]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
"ldr r9, [%[a], #68]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14204,7 +13924,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #68]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+18] += m[18] * mu\n\t"
- "ldr r7, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #72]\n\t"
"ldr r9, [%[a], #72]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14213,7 +13933,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #72]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+19] += m[19] * mu\n\t"
- "ldr r7, [%[m], #76]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
"ldr r9, [%[a], #76]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14222,7 +13942,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #76]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+20] += m[20] * mu\n\t"
- "ldr r7, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #80]\n\t"
"ldr r9, [%[a], #80]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14231,7 +13951,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #80]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+21] += m[21] * mu\n\t"
- "ldr r7, [%[m], #84]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
"ldr r9, [%[a], #84]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14240,7 +13960,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #84]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+22] += m[22] * mu\n\t"
- "ldr r7, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #88]\n\t"
"ldr r9, [%[a], #88]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14249,7 +13969,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #88]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+23] += m[23] * mu\n\t"
- "ldr r7, [%[m], #92]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
"ldr r9, [%[a], #92]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14258,7 +13978,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #92]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+24] += m[24] * mu\n\t"
- "ldr r7, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #96]\n\t"
"ldr r9, [%[a], #96]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14267,7 +13987,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #96]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+25] += m[25] * mu\n\t"
- "ldr r7, [%[m], #100]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
"ldr r9, [%[a], #100]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14276,7 +13996,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #100]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+26] += m[26] * mu\n\t"
- "ldr r7, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #104]\n\t"
"ldr r9, [%[a], #104]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14285,7 +14005,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #104]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+27] += m[27] * mu\n\t"
- "ldr r7, [%[m], #108]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
"ldr r9, [%[a], #108]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14294,7 +14014,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #108]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+28] += m[28] * mu\n\t"
- "ldr r7, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #112]\n\t"
"ldr r9, [%[a], #112]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14303,7 +14023,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #112]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+29] += m[29] * mu\n\t"
- "ldr r7, [%[m], #116]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
"ldr r9, [%[a], #116]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14312,7 +14032,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #116]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+30] += m[30] * mu\n\t"
- "ldr r7, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #120]\n\t"
"ldr r9, [%[a], #120]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14321,7 +14041,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #120]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+31] += m[31] * mu\n\t"
- "ldr r7, [%[m], #124]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
"ldr r9, [%[a], #124]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14330,7 +14050,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #124]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+32] += m[32] * mu\n\t"
- "ldr r7, [%[m], #128]\n\t"
+ "ldr r7, [%[m], #128]\n\t"
"ldr r9, [%[a], #128]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14339,7 +14059,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #128]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+33] += m[33] * mu\n\t"
- "ldr r7, [%[m], #132]\n\t"
+ "ldr r7, [%[m], #132]\n\t"
"ldr r9, [%[a], #132]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14348,7 +14068,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #132]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+34] += m[34] * mu\n\t"
- "ldr r7, [%[m], #136]\n\t"
+ "ldr r7, [%[m], #136]\n\t"
"ldr r9, [%[a], #136]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14357,7 +14077,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #136]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+35] += m[35] * mu\n\t"
- "ldr r7, [%[m], #140]\n\t"
+ "ldr r7, [%[m], #140]\n\t"
"ldr r9, [%[a], #140]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14366,7 +14086,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #140]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+36] += m[36] * mu\n\t"
- "ldr r7, [%[m], #144]\n\t"
+ "ldr r7, [%[m], #144]\n\t"
"ldr r9, [%[a], #144]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14375,7 +14095,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #144]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+37] += m[37] * mu\n\t"
- "ldr r7, [%[m], #148]\n\t"
+ "ldr r7, [%[m], #148]\n\t"
"ldr r9, [%[a], #148]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14384,7 +14104,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #148]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+38] += m[38] * mu\n\t"
- "ldr r7, [%[m], #152]\n\t"
+ "ldr r7, [%[m], #152]\n\t"
"ldr r9, [%[a], #152]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14393,7 +14113,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #152]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+39] += m[39] * mu\n\t"
- "ldr r7, [%[m], #156]\n\t"
+ "ldr r7, [%[m], #156]\n\t"
"ldr r9, [%[a], #156]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14402,7 +14122,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #156]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+40] += m[40] * mu\n\t"
- "ldr r7, [%[m], #160]\n\t"
+ "ldr r7, [%[m], #160]\n\t"
"ldr r9, [%[a], #160]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14411,7 +14131,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #160]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+41] += m[41] * mu\n\t"
- "ldr r7, [%[m], #164]\n\t"
+ "ldr r7, [%[m], #164]\n\t"
"ldr r9, [%[a], #164]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14420,7 +14140,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #164]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+42] += m[42] * mu\n\t"
- "ldr r7, [%[m], #168]\n\t"
+ "ldr r7, [%[m], #168]\n\t"
"ldr r9, [%[a], #168]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14429,7 +14149,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #168]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+43] += m[43] * mu\n\t"
- "ldr r7, [%[m], #172]\n\t"
+ "ldr r7, [%[m], #172]\n\t"
"ldr r9, [%[a], #172]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14438,7 +14158,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #172]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+44] += m[44] * mu\n\t"
- "ldr r7, [%[m], #176]\n\t"
+ "ldr r7, [%[m], #176]\n\t"
"ldr r9, [%[a], #176]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14447,7 +14167,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #176]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+45] += m[45] * mu\n\t"
- "ldr r7, [%[m], #180]\n\t"
+ "ldr r7, [%[m], #180]\n\t"
"ldr r9, [%[a], #180]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14456,7 +14176,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #180]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+46] += m[46] * mu\n\t"
- "ldr r7, [%[m], #184]\n\t"
+ "ldr r7, [%[m], #184]\n\t"
"ldr r9, [%[a], #184]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -14487,7 +14207,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
@@ -14502,8 +14222,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_48(r, a, b);
sp_3072_mont_reduce_48(r, m, mp);
@@ -14516,8 +14236,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_48(r, a);
sp_3072_mont_reduce_48(r, m, mp);
@@ -14570,371 +14290,325 @@ static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #44]\n\t"
"# A[12] * B\n\t"
"ldr r8, [%[a], #48]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[13] * B\n\t"
"ldr r8, [%[a], #52]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[14] * B\n\t"
"ldr r8, [%[a], #56]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #56]\n\t"
"# A[15] * B\n\t"
"ldr r8, [%[a], #60]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #60]\n\t"
"# A[16] * B\n\t"
"ldr r8, [%[a], #64]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #64]\n\t"
"# A[17] * B\n\t"
"ldr r8, [%[a], #68]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #68]\n\t"
"# A[18] * B\n\t"
"ldr r8, [%[a], #72]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #72]\n\t"
"# A[19] * B\n\t"
"ldr r8, [%[a], #76]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #76]\n\t"
"# A[20] * B\n\t"
"ldr r8, [%[a], #80]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[21] * B\n\t"
"ldr r8, [%[a], #84]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[22] * B\n\t"
"ldr r8, [%[a], #88]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #88]\n\t"
"# A[23] * B\n\t"
"ldr r8, [%[a], #92]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #92]\n\t"
"# A[24] * B\n\t"
"ldr r8, [%[a], #96]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #96]\n\t"
"# A[25] * B\n\t"
"ldr r8, [%[a], #100]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #100]\n\t"
"# A[26] * B\n\t"
"ldr r8, [%[a], #104]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #104]\n\t"
"# A[27] * B\n\t"
"ldr r8, [%[a], #108]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #108]\n\t"
"# A[28] * B\n\t"
"ldr r8, [%[a], #112]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #112]\n\t"
"# A[29] * B\n\t"
"ldr r8, [%[a], #116]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #116]\n\t"
"# A[30] * B\n\t"
"ldr r8, [%[a], #120]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #120]\n\t"
"# A[31] * B\n\t"
"ldr r8, [%[a], #124]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #124]\n\t"
"# A[32] * B\n\t"
"ldr r8, [%[a], #128]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #128]\n\t"
"# A[33] * B\n\t"
"ldr r8, [%[a], #132]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #132]\n\t"
"# A[34] * B\n\t"
"ldr r8, [%[a], #136]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #136]\n\t"
"# A[35] * B\n\t"
"ldr r8, [%[a], #140]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #140]\n\t"
"# A[36] * B\n\t"
"ldr r8, [%[a], #144]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #144]\n\t"
"# A[37] * B\n\t"
"ldr r8, [%[a], #148]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #148]\n\t"
"# A[38] * B\n\t"
"ldr r8, [%[a], #152]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #152]\n\t"
"# A[39] * B\n\t"
"ldr r8, [%[a], #156]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #156]\n\t"
"# A[40] * B\n\t"
"ldr r8, [%[a], #160]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #160]\n\t"
"# A[41] * B\n\t"
"ldr r8, [%[a], #164]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #164]\n\t"
"# A[42] * B\n\t"
"ldr r8, [%[a], #168]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #168]\n\t"
"# A[43] * B\n\t"
"ldr r8, [%[a], #172]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #172]\n\t"
"# A[44] * B\n\t"
"ldr r8, [%[a], #176]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #176]\n\t"
"# A[45] * B\n\t"
"ldr r8, [%[a], #180]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #180]\n\t"
"# A[46] * B\n\t"
"ldr r8, [%[a], #184]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #184]\n\t"
"# A[47] * B\n\t"
"ldr r8, [%[a], #188]\n\t"
@@ -15667,7 +15341,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -15733,34 +15408,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -15812,7 +15487,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -15894,34 +15570,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -15952,7 +15628,7 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -15969,7 +15645,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m)
sp_3072_sub_in_place_96(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -16508,6 +16184,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -16516,13 +16193,12 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -16530,7 +16206,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -16538,7 +16214,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16547,7 +16223,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16556,7 +16232,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16565,7 +16241,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16574,7 +16250,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16583,7 +16259,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16592,7 +16268,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16601,7 +16277,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16610,7 +16286,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #40]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+11] += m[11] * mu\n\t"
- "ldr r7, [%[m], #44]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
"ldr r9, [%[a], #44]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16619,7 +16295,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #44]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+12] += m[12] * mu\n\t"
- "ldr r7, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #48]\n\t"
"ldr r9, [%[a], #48]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16628,7 +16304,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #48]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+13] += m[13] * mu\n\t"
- "ldr r7, [%[m], #52]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
"ldr r9, [%[a], #52]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16637,7 +16313,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #52]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+14] += m[14] * mu\n\t"
- "ldr r7, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #56]\n\t"
"ldr r9, [%[a], #56]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16646,7 +16322,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #56]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+15] += m[15] * mu\n\t"
- "ldr r7, [%[m], #60]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
"ldr r9, [%[a], #60]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16655,7 +16331,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #60]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+16] += m[16] * mu\n\t"
- "ldr r7, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #64]\n\t"
"ldr r9, [%[a], #64]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16664,7 +16340,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #64]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+17] += m[17] * mu\n\t"
- "ldr r7, [%[m], #68]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
"ldr r9, [%[a], #68]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16673,7 +16349,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #68]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+18] += m[18] * mu\n\t"
- "ldr r7, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #72]\n\t"
"ldr r9, [%[a], #72]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16682,7 +16358,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #72]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+19] += m[19] * mu\n\t"
- "ldr r7, [%[m], #76]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
"ldr r9, [%[a], #76]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16691,7 +16367,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #76]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+20] += m[20] * mu\n\t"
- "ldr r7, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #80]\n\t"
"ldr r9, [%[a], #80]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16700,7 +16376,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #80]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+21] += m[21] * mu\n\t"
- "ldr r7, [%[m], #84]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
"ldr r9, [%[a], #84]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16709,7 +16385,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #84]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+22] += m[22] * mu\n\t"
- "ldr r7, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #88]\n\t"
"ldr r9, [%[a], #88]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16718,7 +16394,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #88]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+23] += m[23] * mu\n\t"
- "ldr r7, [%[m], #92]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
"ldr r9, [%[a], #92]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16727,7 +16403,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #92]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+24] += m[24] * mu\n\t"
- "ldr r7, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #96]\n\t"
"ldr r9, [%[a], #96]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16736,7 +16412,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #96]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+25] += m[25] * mu\n\t"
- "ldr r7, [%[m], #100]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
"ldr r9, [%[a], #100]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16745,7 +16421,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #100]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+26] += m[26] * mu\n\t"
- "ldr r7, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #104]\n\t"
"ldr r9, [%[a], #104]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16754,7 +16430,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #104]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+27] += m[27] * mu\n\t"
- "ldr r7, [%[m], #108]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
"ldr r9, [%[a], #108]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16763,7 +16439,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #108]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+28] += m[28] * mu\n\t"
- "ldr r7, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #112]\n\t"
"ldr r9, [%[a], #112]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16772,7 +16448,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #112]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+29] += m[29] * mu\n\t"
- "ldr r7, [%[m], #116]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
"ldr r9, [%[a], #116]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16781,7 +16457,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #116]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+30] += m[30] * mu\n\t"
- "ldr r7, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #120]\n\t"
"ldr r9, [%[a], #120]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16790,7 +16466,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #120]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+31] += m[31] * mu\n\t"
- "ldr r7, [%[m], #124]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
"ldr r9, [%[a], #124]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16799,7 +16475,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #124]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+32] += m[32] * mu\n\t"
- "ldr r7, [%[m], #128]\n\t"
+ "ldr r7, [%[m], #128]\n\t"
"ldr r9, [%[a], #128]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16808,7 +16484,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #128]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+33] += m[33] * mu\n\t"
- "ldr r7, [%[m], #132]\n\t"
+ "ldr r7, [%[m], #132]\n\t"
"ldr r9, [%[a], #132]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16817,7 +16493,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #132]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+34] += m[34] * mu\n\t"
- "ldr r7, [%[m], #136]\n\t"
+ "ldr r7, [%[m], #136]\n\t"
"ldr r9, [%[a], #136]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16826,7 +16502,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #136]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+35] += m[35] * mu\n\t"
- "ldr r7, [%[m], #140]\n\t"
+ "ldr r7, [%[m], #140]\n\t"
"ldr r9, [%[a], #140]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16835,7 +16511,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #140]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+36] += m[36] * mu\n\t"
- "ldr r7, [%[m], #144]\n\t"
+ "ldr r7, [%[m], #144]\n\t"
"ldr r9, [%[a], #144]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16844,7 +16520,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #144]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+37] += m[37] * mu\n\t"
- "ldr r7, [%[m], #148]\n\t"
+ "ldr r7, [%[m], #148]\n\t"
"ldr r9, [%[a], #148]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16853,7 +16529,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #148]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+38] += m[38] * mu\n\t"
- "ldr r7, [%[m], #152]\n\t"
+ "ldr r7, [%[m], #152]\n\t"
"ldr r9, [%[a], #152]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16862,7 +16538,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #152]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+39] += m[39] * mu\n\t"
- "ldr r7, [%[m], #156]\n\t"
+ "ldr r7, [%[m], #156]\n\t"
"ldr r9, [%[a], #156]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16871,7 +16547,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #156]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+40] += m[40] * mu\n\t"
- "ldr r7, [%[m], #160]\n\t"
+ "ldr r7, [%[m], #160]\n\t"
"ldr r9, [%[a], #160]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16880,7 +16556,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #160]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+41] += m[41] * mu\n\t"
- "ldr r7, [%[m], #164]\n\t"
+ "ldr r7, [%[m], #164]\n\t"
"ldr r9, [%[a], #164]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16889,7 +16565,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #164]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+42] += m[42] * mu\n\t"
- "ldr r7, [%[m], #168]\n\t"
+ "ldr r7, [%[m], #168]\n\t"
"ldr r9, [%[a], #168]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16898,7 +16574,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #168]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+43] += m[43] * mu\n\t"
- "ldr r7, [%[m], #172]\n\t"
+ "ldr r7, [%[m], #172]\n\t"
"ldr r9, [%[a], #172]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16907,7 +16583,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #172]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+44] += m[44] * mu\n\t"
- "ldr r7, [%[m], #176]\n\t"
+ "ldr r7, [%[m], #176]\n\t"
"ldr r9, [%[a], #176]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16916,7 +16592,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #176]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+45] += m[45] * mu\n\t"
- "ldr r7, [%[m], #180]\n\t"
+ "ldr r7, [%[m], #180]\n\t"
"ldr r9, [%[a], #180]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16925,7 +16601,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #180]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+46] += m[46] * mu\n\t"
- "ldr r7, [%[m], #184]\n\t"
+ "ldr r7, [%[m], #184]\n\t"
"ldr r9, [%[a], #184]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16934,7 +16610,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #184]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+47] += m[47] * mu\n\t"
- "ldr r7, [%[m], #188]\n\t"
+ "ldr r7, [%[m], #188]\n\t"
"ldr r9, [%[a], #188]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16943,7 +16619,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #188]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+48] += m[48] * mu\n\t"
- "ldr r7, [%[m], #192]\n\t"
+ "ldr r7, [%[m], #192]\n\t"
"ldr r9, [%[a], #192]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16952,7 +16628,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #192]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+49] += m[49] * mu\n\t"
- "ldr r7, [%[m], #196]\n\t"
+ "ldr r7, [%[m], #196]\n\t"
"ldr r9, [%[a], #196]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16961,7 +16637,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #196]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+50] += m[50] * mu\n\t"
- "ldr r7, [%[m], #200]\n\t"
+ "ldr r7, [%[m], #200]\n\t"
"ldr r9, [%[a], #200]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16970,7 +16646,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #200]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+51] += m[51] * mu\n\t"
- "ldr r7, [%[m], #204]\n\t"
+ "ldr r7, [%[m], #204]\n\t"
"ldr r9, [%[a], #204]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16979,7 +16655,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #204]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+52] += m[52] * mu\n\t"
- "ldr r7, [%[m], #208]\n\t"
+ "ldr r7, [%[m], #208]\n\t"
"ldr r9, [%[a], #208]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16988,7 +16664,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #208]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+53] += m[53] * mu\n\t"
- "ldr r7, [%[m], #212]\n\t"
+ "ldr r7, [%[m], #212]\n\t"
"ldr r9, [%[a], #212]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -16997,7 +16673,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #212]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+54] += m[54] * mu\n\t"
- "ldr r7, [%[m], #216]\n\t"
+ "ldr r7, [%[m], #216]\n\t"
"ldr r9, [%[a], #216]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17006,7 +16682,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #216]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+55] += m[55] * mu\n\t"
- "ldr r7, [%[m], #220]\n\t"
+ "ldr r7, [%[m], #220]\n\t"
"ldr r9, [%[a], #220]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17015,7 +16691,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #220]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+56] += m[56] * mu\n\t"
- "ldr r7, [%[m], #224]\n\t"
+ "ldr r7, [%[m], #224]\n\t"
"ldr r9, [%[a], #224]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17024,7 +16700,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #224]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+57] += m[57] * mu\n\t"
- "ldr r7, [%[m], #228]\n\t"
+ "ldr r7, [%[m], #228]\n\t"
"ldr r9, [%[a], #228]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17033,7 +16709,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #228]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+58] += m[58] * mu\n\t"
- "ldr r7, [%[m], #232]\n\t"
+ "ldr r7, [%[m], #232]\n\t"
"ldr r9, [%[a], #232]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17042,7 +16718,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #232]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+59] += m[59] * mu\n\t"
- "ldr r7, [%[m], #236]\n\t"
+ "ldr r7, [%[m], #236]\n\t"
"ldr r9, [%[a], #236]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17051,7 +16727,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #236]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+60] += m[60] * mu\n\t"
- "ldr r7, [%[m], #240]\n\t"
+ "ldr r7, [%[m], #240]\n\t"
"ldr r9, [%[a], #240]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17060,7 +16736,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #240]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+61] += m[61] * mu\n\t"
- "ldr r7, [%[m], #244]\n\t"
+ "ldr r7, [%[m], #244]\n\t"
"ldr r9, [%[a], #244]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17069,7 +16745,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #244]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+62] += m[62] * mu\n\t"
- "ldr r7, [%[m], #248]\n\t"
+ "ldr r7, [%[m], #248]\n\t"
"ldr r9, [%[a], #248]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17078,7 +16754,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #248]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+63] += m[63] * mu\n\t"
- "ldr r7, [%[m], #252]\n\t"
+ "ldr r7, [%[m], #252]\n\t"
"ldr r9, [%[a], #252]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17087,7 +16763,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #252]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+64] += m[64] * mu\n\t"
- "ldr r7, [%[m], #256]\n\t"
+ "ldr r7, [%[m], #256]\n\t"
"ldr r9, [%[a], #256]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17096,7 +16772,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #256]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+65] += m[65] * mu\n\t"
- "ldr r7, [%[m], #260]\n\t"
+ "ldr r7, [%[m], #260]\n\t"
"ldr r9, [%[a], #260]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17105,7 +16781,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #260]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+66] += m[66] * mu\n\t"
- "ldr r7, [%[m], #264]\n\t"
+ "ldr r7, [%[m], #264]\n\t"
"ldr r9, [%[a], #264]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17114,7 +16790,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #264]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+67] += m[67] * mu\n\t"
- "ldr r7, [%[m], #268]\n\t"
+ "ldr r7, [%[m], #268]\n\t"
"ldr r9, [%[a], #268]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17123,7 +16799,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #268]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+68] += m[68] * mu\n\t"
- "ldr r7, [%[m], #272]\n\t"
+ "ldr r7, [%[m], #272]\n\t"
"ldr r9, [%[a], #272]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17132,7 +16808,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #272]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+69] += m[69] * mu\n\t"
- "ldr r7, [%[m], #276]\n\t"
+ "ldr r7, [%[m], #276]\n\t"
"ldr r9, [%[a], #276]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17141,7 +16817,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #276]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+70] += m[70] * mu\n\t"
- "ldr r7, [%[m], #280]\n\t"
+ "ldr r7, [%[m], #280]\n\t"
"ldr r9, [%[a], #280]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17150,7 +16826,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #280]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+71] += m[71] * mu\n\t"
- "ldr r7, [%[m], #284]\n\t"
+ "ldr r7, [%[m], #284]\n\t"
"ldr r9, [%[a], #284]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17159,7 +16835,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #284]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+72] += m[72] * mu\n\t"
- "ldr r7, [%[m], #288]\n\t"
+ "ldr r7, [%[m], #288]\n\t"
"ldr r9, [%[a], #288]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17168,7 +16844,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #288]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+73] += m[73] * mu\n\t"
- "ldr r7, [%[m], #292]\n\t"
+ "ldr r7, [%[m], #292]\n\t"
"ldr r9, [%[a], #292]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17177,7 +16853,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #292]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+74] += m[74] * mu\n\t"
- "ldr r7, [%[m], #296]\n\t"
+ "ldr r7, [%[m], #296]\n\t"
"ldr r9, [%[a], #296]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17186,7 +16862,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #296]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+75] += m[75] * mu\n\t"
- "ldr r7, [%[m], #300]\n\t"
+ "ldr r7, [%[m], #300]\n\t"
"ldr r9, [%[a], #300]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17195,7 +16871,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #300]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+76] += m[76] * mu\n\t"
- "ldr r7, [%[m], #304]\n\t"
+ "ldr r7, [%[m], #304]\n\t"
"ldr r9, [%[a], #304]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17204,7 +16880,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #304]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+77] += m[77] * mu\n\t"
- "ldr r7, [%[m], #308]\n\t"
+ "ldr r7, [%[m], #308]\n\t"
"ldr r9, [%[a], #308]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17213,7 +16889,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #308]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+78] += m[78] * mu\n\t"
- "ldr r7, [%[m], #312]\n\t"
+ "ldr r7, [%[m], #312]\n\t"
"ldr r9, [%[a], #312]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17222,7 +16898,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #312]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+79] += m[79] * mu\n\t"
- "ldr r7, [%[m], #316]\n\t"
+ "ldr r7, [%[m], #316]\n\t"
"ldr r9, [%[a], #316]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17231,7 +16907,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #316]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+80] += m[80] * mu\n\t"
- "ldr r7, [%[m], #320]\n\t"
+ "ldr r7, [%[m], #320]\n\t"
"ldr r9, [%[a], #320]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17240,7 +16916,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #320]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+81] += m[81] * mu\n\t"
- "ldr r7, [%[m], #324]\n\t"
+ "ldr r7, [%[m], #324]\n\t"
"ldr r9, [%[a], #324]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17249,7 +16925,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #324]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+82] += m[82] * mu\n\t"
- "ldr r7, [%[m], #328]\n\t"
+ "ldr r7, [%[m], #328]\n\t"
"ldr r9, [%[a], #328]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17258,7 +16934,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #328]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+83] += m[83] * mu\n\t"
- "ldr r7, [%[m], #332]\n\t"
+ "ldr r7, [%[m], #332]\n\t"
"ldr r9, [%[a], #332]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17267,7 +16943,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #332]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+84] += m[84] * mu\n\t"
- "ldr r7, [%[m], #336]\n\t"
+ "ldr r7, [%[m], #336]\n\t"
"ldr r9, [%[a], #336]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17276,7 +16952,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #336]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+85] += m[85] * mu\n\t"
- "ldr r7, [%[m], #340]\n\t"
+ "ldr r7, [%[m], #340]\n\t"
"ldr r9, [%[a], #340]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17285,7 +16961,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #340]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+86] += m[86] * mu\n\t"
- "ldr r7, [%[m], #344]\n\t"
+ "ldr r7, [%[m], #344]\n\t"
"ldr r9, [%[a], #344]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17294,7 +16970,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #344]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+87] += m[87] * mu\n\t"
- "ldr r7, [%[m], #348]\n\t"
+ "ldr r7, [%[m], #348]\n\t"
"ldr r9, [%[a], #348]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17303,7 +16979,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #348]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+88] += m[88] * mu\n\t"
- "ldr r7, [%[m], #352]\n\t"
+ "ldr r7, [%[m], #352]\n\t"
"ldr r9, [%[a], #352]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17312,7 +16988,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #352]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+89] += m[89] * mu\n\t"
- "ldr r7, [%[m], #356]\n\t"
+ "ldr r7, [%[m], #356]\n\t"
"ldr r9, [%[a], #356]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17321,7 +16997,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #356]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+90] += m[90] * mu\n\t"
- "ldr r7, [%[m], #360]\n\t"
+ "ldr r7, [%[m], #360]\n\t"
"ldr r9, [%[a], #360]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17330,7 +17006,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #360]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+91] += m[91] * mu\n\t"
- "ldr r7, [%[m], #364]\n\t"
+ "ldr r7, [%[m], #364]\n\t"
"ldr r9, [%[a], #364]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17339,7 +17015,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #364]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+92] += m[92] * mu\n\t"
- "ldr r7, [%[m], #368]\n\t"
+ "ldr r7, [%[m], #368]\n\t"
"ldr r9, [%[a], #368]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17348,7 +17024,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #368]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+93] += m[93] * mu\n\t"
- "ldr r7, [%[m], #372]\n\t"
+ "ldr r7, [%[m], #372]\n\t"
"ldr r9, [%[a], #372]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17357,7 +17033,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #372]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+94] += m[94] * mu\n\t"
- "ldr r7, [%[m], #376]\n\t"
+ "ldr r7, [%[m], #376]\n\t"
"ldr r9, [%[a], #376]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -17388,7 +17064,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca);
@@ -17403,8 +17079,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_96(r, a, b);
sp_3072_mont_reduce_96(r, m, mp);
@@ -17417,8 +17093,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_96(r, a);
sp_3072_mont_reduce_96(r, m, mp);
@@ -18756,7 +18432,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -18822,34 +18499,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -18901,7 +18578,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -18983,34 +18661,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -19055,11 +18733,13 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[192], m[96], r[192];
+ sp_digit a[192];
+ sp_digit m[96];
+ sp_digit r[192];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -19482,9 +19162,9 @@ static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -19548,8 +19228,11 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[96 * 2];
- sp_digit p[48], q[48], dp[48];
- sp_digit tmpa[96], tmpb[96];
+ sp_digit p[48];
+ sp_digit q[48];
+ sp_digit dp[48];
+ sp_digit tmpa[96];
+ sp_digit tmpb[96];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -19646,7 +19329,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -19669,17 +19352,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 96;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -19692,14 +19377,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -19726,10 +19413,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -20372,10 +20062,12 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -20410,34 +20102,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_3072_lshift_96(r, norm, (byte)y);
+ sp_3072_lshift_96(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -20448,7 +20140,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_3072_mont_sqr_96(r, r, m, mp);
sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_lshift_96(r, r, (byte)y);
+ sp_3072_lshift_96(r, r, y);
sp_3072_mul_d_96(tmp, norm, r[96]);
r[96] = 0;
o = sp_3072_add_96(r, r, tmp);
@@ -20484,11 +20176,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
word32 i;
@@ -20523,6 +20217,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -20544,10 +20239,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -20584,7 +20282,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -20598,7 +20296,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -20640,7 +20339,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -20674,7 +20374,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -20713,7 +20415,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 4096 / 8 - 1;
a[j] = 0;
@@ -21822,7 +21527,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
sp_digit a1[64];
sp_digit b1[64];
sp_digit z2[128];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_64(a1, a, &a[64]);
cb = sp_2048_add_64(b1, b, &b[64]);
@@ -22101,7 +21808,8 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -22110,7 +21818,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -22160,1011 +21868,885 @@ static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #44]\n\t"
"# A[12] * B\n\t"
"ldr r8, [%[a], #48]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #48]\n\t"
"# A[13] * B\n\t"
"ldr r8, [%[a], #52]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #52]\n\t"
"# A[14] * B\n\t"
"ldr r8, [%[a], #56]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #56]\n\t"
"# A[15] * B\n\t"
"ldr r8, [%[a], #60]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #60]\n\t"
"# A[16] * B\n\t"
"ldr r8, [%[a], #64]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #64]\n\t"
"# A[17] * B\n\t"
"ldr r8, [%[a], #68]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #68]\n\t"
"# A[18] * B\n\t"
"ldr r8, [%[a], #72]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #72]\n\t"
"# A[19] * B\n\t"
"ldr r8, [%[a], #76]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #76]\n\t"
"# A[20] * B\n\t"
"ldr r8, [%[a], #80]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[21] * B\n\t"
"ldr r8, [%[a], #84]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[22] * B\n\t"
"ldr r8, [%[a], #88]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #88]\n\t"
"# A[23] * B\n\t"
"ldr r8, [%[a], #92]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #92]\n\t"
"# A[24] * B\n\t"
"ldr r8, [%[a], #96]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #96]\n\t"
"# A[25] * B\n\t"
"ldr r8, [%[a], #100]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #100]\n\t"
"# A[26] * B\n\t"
"ldr r8, [%[a], #104]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #104]\n\t"
"# A[27] * B\n\t"
"ldr r8, [%[a], #108]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #108]\n\t"
"# A[28] * B\n\t"
"ldr r8, [%[a], #112]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #112]\n\t"
"# A[29] * B\n\t"
"ldr r8, [%[a], #116]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #116]\n\t"
"# A[30] * B\n\t"
"ldr r8, [%[a], #120]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #120]\n\t"
"# A[31] * B\n\t"
"ldr r8, [%[a], #124]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #124]\n\t"
"# A[32] * B\n\t"
"ldr r8, [%[a], #128]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #128]\n\t"
"# A[33] * B\n\t"
"ldr r8, [%[a], #132]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #132]\n\t"
"# A[34] * B\n\t"
"ldr r8, [%[a], #136]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #136]\n\t"
"# A[35] * B\n\t"
"ldr r8, [%[a], #140]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #140]\n\t"
"# A[36] * B\n\t"
"ldr r8, [%[a], #144]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #144]\n\t"
"# A[37] * B\n\t"
"ldr r8, [%[a], #148]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #148]\n\t"
"# A[38] * B\n\t"
"ldr r8, [%[a], #152]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #152]\n\t"
"# A[39] * B\n\t"
"ldr r8, [%[a], #156]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #156]\n\t"
"# A[40] * B\n\t"
"ldr r8, [%[a], #160]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #160]\n\t"
"# A[41] * B\n\t"
"ldr r8, [%[a], #164]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #164]\n\t"
"# A[42] * B\n\t"
"ldr r8, [%[a], #168]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #168]\n\t"
"# A[43] * B\n\t"
"ldr r8, [%[a], #172]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #172]\n\t"
"# A[44] * B\n\t"
"ldr r8, [%[a], #176]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #176]\n\t"
"# A[45] * B\n\t"
"ldr r8, [%[a], #180]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #180]\n\t"
"# A[46] * B\n\t"
"ldr r8, [%[a], #184]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #184]\n\t"
"# A[47] * B\n\t"
"ldr r8, [%[a], #188]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #188]\n\t"
"# A[48] * B\n\t"
"ldr r8, [%[a], #192]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #192]\n\t"
"# A[49] * B\n\t"
"ldr r8, [%[a], #196]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #196]\n\t"
"# A[50] * B\n\t"
"ldr r8, [%[a], #200]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #200]\n\t"
"# A[51] * B\n\t"
"ldr r8, [%[a], #204]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #204]\n\t"
"# A[52] * B\n\t"
"ldr r8, [%[a], #208]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #208]\n\t"
"# A[53] * B\n\t"
"ldr r8, [%[a], #212]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #212]\n\t"
"# A[54] * B\n\t"
"ldr r8, [%[a], #216]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #216]\n\t"
"# A[55] * B\n\t"
"ldr r8, [%[a], #220]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #220]\n\t"
"# A[56] * B\n\t"
"ldr r8, [%[a], #224]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #224]\n\t"
"# A[57] * B\n\t"
"ldr r8, [%[a], #228]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #228]\n\t"
"# A[58] * B\n\t"
"ldr r8, [%[a], #232]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #232]\n\t"
"# A[59] * B\n\t"
"ldr r8, [%[a], #236]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #236]\n\t"
"# A[60] * B\n\t"
"ldr r8, [%[a], #240]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #240]\n\t"
"# A[61] * B\n\t"
"ldr r8, [%[a], #244]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #244]\n\t"
"# A[62] * B\n\t"
"ldr r8, [%[a], #248]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #248]\n\t"
"# A[63] * B\n\t"
"ldr r8, [%[a], #252]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #252]\n\t"
"# A[64] * B\n\t"
"ldr r8, [%[a], #256]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #256]\n\t"
"# A[65] * B\n\t"
"ldr r8, [%[a], #260]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #260]\n\t"
"# A[66] * B\n\t"
"ldr r8, [%[a], #264]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #264]\n\t"
"# A[67] * B\n\t"
"ldr r8, [%[a], #268]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #268]\n\t"
"# A[68] * B\n\t"
"ldr r8, [%[a], #272]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #272]\n\t"
"# A[69] * B\n\t"
"ldr r8, [%[a], #276]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #276]\n\t"
"# A[70] * B\n\t"
"ldr r8, [%[a], #280]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #280]\n\t"
"# A[71] * B\n\t"
"ldr r8, [%[a], #284]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #284]\n\t"
"# A[72] * B\n\t"
"ldr r8, [%[a], #288]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #288]\n\t"
"# A[73] * B\n\t"
"ldr r8, [%[a], #292]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #292]\n\t"
"# A[74] * B\n\t"
"ldr r8, [%[a], #296]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #296]\n\t"
"# A[75] * B\n\t"
"ldr r8, [%[a], #300]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #300]\n\t"
"# A[76] * B\n\t"
"ldr r8, [%[a], #304]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #304]\n\t"
"# A[77] * B\n\t"
"ldr r8, [%[a], #308]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #308]\n\t"
"# A[78] * B\n\t"
"ldr r8, [%[a], #312]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #312]\n\t"
"# A[79] * B\n\t"
"ldr r8, [%[a], #316]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #316]\n\t"
"# A[80] * B\n\t"
"ldr r8, [%[a], #320]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #320]\n\t"
"# A[81] * B\n\t"
"ldr r8, [%[a], #324]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #324]\n\t"
"# A[82] * B\n\t"
"ldr r8, [%[a], #328]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #328]\n\t"
"# A[83] * B\n\t"
"ldr r8, [%[a], #332]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #332]\n\t"
"# A[84] * B\n\t"
"ldr r8, [%[a], #336]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #336]\n\t"
"# A[85] * B\n\t"
"ldr r8, [%[a], #340]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #340]\n\t"
"# A[86] * B\n\t"
"ldr r8, [%[a], #344]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #344]\n\t"
"# A[87] * B\n\t"
"ldr r8, [%[a], #348]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #348]\n\t"
"# A[88] * B\n\t"
"ldr r8, [%[a], #352]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #352]\n\t"
"# A[89] * B\n\t"
"ldr r8, [%[a], #356]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #356]\n\t"
"# A[90] * B\n\t"
"ldr r8, [%[a], #360]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #360]\n\t"
"# A[91] * B\n\t"
"ldr r8, [%[a], #364]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #364]\n\t"
"# A[92] * B\n\t"
"ldr r8, [%[a], #368]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #368]\n\t"
"# A[93] * B\n\t"
"ldr r8, [%[a], #372]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #372]\n\t"
"# A[94] * B\n\t"
"ldr r8, [%[a], #376]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #376]\n\t"
"# A[95] * B\n\t"
"ldr r8, [%[a], #380]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #380]\n\t"
"# A[96] * B\n\t"
"ldr r8, [%[a], #384]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #384]\n\t"
"# A[97] * B\n\t"
"ldr r8, [%[a], #388]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #388]\n\t"
"# A[98] * B\n\t"
"ldr r8, [%[a], #392]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #392]\n\t"
"# A[99] * B\n\t"
"ldr r8, [%[a], #396]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #396]\n\t"
"# A[100] * B\n\t"
"ldr r8, [%[a], #400]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #400]\n\t"
"# A[101] * B\n\t"
"ldr r8, [%[a], #404]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #404]\n\t"
"# A[102] * B\n\t"
"ldr r8, [%[a], #408]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #408]\n\t"
"# A[103] * B\n\t"
"ldr r8, [%[a], #412]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #412]\n\t"
"# A[104] * B\n\t"
"ldr r8, [%[a], #416]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #416]\n\t"
"# A[105] * B\n\t"
"ldr r8, [%[a], #420]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #420]\n\t"
"# A[106] * B\n\t"
"ldr r8, [%[a], #424]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #424]\n\t"
"# A[107] * B\n\t"
"ldr r8, [%[a], #428]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #428]\n\t"
"# A[108] * B\n\t"
"ldr r8, [%[a], #432]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #432]\n\t"
"# A[109] * B\n\t"
"ldr r8, [%[a], #436]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #436]\n\t"
"# A[110] * B\n\t"
"ldr r8, [%[a], #440]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #440]\n\t"
"# A[111] * B\n\t"
"ldr r8, [%[a], #444]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #444]\n\t"
"# A[112] * B\n\t"
"ldr r8, [%[a], #448]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #448]\n\t"
"# A[113] * B\n\t"
"ldr r8, [%[a], #452]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #452]\n\t"
"# A[114] * B\n\t"
"ldr r8, [%[a], #456]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #456]\n\t"
"# A[115] * B\n\t"
"ldr r8, [%[a], #460]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #460]\n\t"
"# A[116] * B\n\t"
"ldr r8, [%[a], #464]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #464]\n\t"
"# A[117] * B\n\t"
"ldr r8, [%[a], #468]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #468]\n\t"
"# A[118] * B\n\t"
"ldr r8, [%[a], #472]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #472]\n\t"
"# A[119] * B\n\t"
"ldr r8, [%[a], #476]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #476]\n\t"
"# A[120] * B\n\t"
"ldr r8, [%[a], #480]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #480]\n\t"
"# A[121] * B\n\t"
"ldr r8, [%[a], #484]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #484]\n\t"
"# A[122] * B\n\t"
"ldr r8, [%[a], #488]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #488]\n\t"
"# A[123] * B\n\t"
"ldr r8, [%[a], #492]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #492]\n\t"
"# A[124] * B\n\t"
"ldr r8, [%[a], #496]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #496]\n\t"
"# A[125] * B\n\t"
"ldr r8, [%[a], #500]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #500]\n\t"
"# A[126] * B\n\t"
"ldr r8, [%[a], #504]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #504]\n\t"
"# A[127] * B\n\t"
"ldr r8, [%[a], #508]\n\t"
@@ -23195,7 +22777,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m)
sp_4096_sub_in_place_128(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -23894,6 +23476,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -23902,13 +23485,12 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -23916,7 +23498,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -23924,7 +23506,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23933,7 +23515,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23942,7 +23524,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23951,7 +23533,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23960,7 +23542,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23969,7 +23551,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23978,7 +23560,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23987,7 +23569,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -23996,7 +23578,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #40]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+11] += m[11] * mu\n\t"
- "ldr r7, [%[m], #44]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
"ldr r9, [%[a], #44]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24005,7 +23587,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #44]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+12] += m[12] * mu\n\t"
- "ldr r7, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #48]\n\t"
"ldr r9, [%[a], #48]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24014,7 +23596,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #48]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+13] += m[13] * mu\n\t"
- "ldr r7, [%[m], #52]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
"ldr r9, [%[a], #52]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24023,7 +23605,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #52]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+14] += m[14] * mu\n\t"
- "ldr r7, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #56]\n\t"
"ldr r9, [%[a], #56]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24032,7 +23614,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #56]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+15] += m[15] * mu\n\t"
- "ldr r7, [%[m], #60]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
"ldr r9, [%[a], #60]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24041,7 +23623,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #60]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+16] += m[16] * mu\n\t"
- "ldr r7, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #64]\n\t"
"ldr r9, [%[a], #64]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24050,7 +23632,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #64]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+17] += m[17] * mu\n\t"
- "ldr r7, [%[m], #68]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
"ldr r9, [%[a], #68]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24059,7 +23641,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #68]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+18] += m[18] * mu\n\t"
- "ldr r7, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #72]\n\t"
"ldr r9, [%[a], #72]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24068,7 +23650,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #72]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+19] += m[19] * mu\n\t"
- "ldr r7, [%[m], #76]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
"ldr r9, [%[a], #76]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24077,7 +23659,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #76]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+20] += m[20] * mu\n\t"
- "ldr r7, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #80]\n\t"
"ldr r9, [%[a], #80]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24086,7 +23668,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #80]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+21] += m[21] * mu\n\t"
- "ldr r7, [%[m], #84]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
"ldr r9, [%[a], #84]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24095,7 +23677,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #84]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+22] += m[22] * mu\n\t"
- "ldr r7, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #88]\n\t"
"ldr r9, [%[a], #88]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24104,7 +23686,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #88]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+23] += m[23] * mu\n\t"
- "ldr r7, [%[m], #92]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
"ldr r9, [%[a], #92]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24113,7 +23695,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #92]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+24] += m[24] * mu\n\t"
- "ldr r7, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #96]\n\t"
"ldr r9, [%[a], #96]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24122,7 +23704,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #96]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+25] += m[25] * mu\n\t"
- "ldr r7, [%[m], #100]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
"ldr r9, [%[a], #100]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24131,7 +23713,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #100]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+26] += m[26] * mu\n\t"
- "ldr r7, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #104]\n\t"
"ldr r9, [%[a], #104]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24140,7 +23722,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #104]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+27] += m[27] * mu\n\t"
- "ldr r7, [%[m], #108]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
"ldr r9, [%[a], #108]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24149,7 +23731,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #108]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+28] += m[28] * mu\n\t"
- "ldr r7, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #112]\n\t"
"ldr r9, [%[a], #112]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24158,7 +23740,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #112]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+29] += m[29] * mu\n\t"
- "ldr r7, [%[m], #116]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
"ldr r9, [%[a], #116]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24167,7 +23749,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #116]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+30] += m[30] * mu\n\t"
- "ldr r7, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #120]\n\t"
"ldr r9, [%[a], #120]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24176,7 +23758,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #120]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+31] += m[31] * mu\n\t"
- "ldr r7, [%[m], #124]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
"ldr r9, [%[a], #124]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24185,7 +23767,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #124]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+32] += m[32] * mu\n\t"
- "ldr r7, [%[m], #128]\n\t"
+ "ldr r7, [%[m], #128]\n\t"
"ldr r9, [%[a], #128]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24194,7 +23776,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #128]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+33] += m[33] * mu\n\t"
- "ldr r7, [%[m], #132]\n\t"
+ "ldr r7, [%[m], #132]\n\t"
"ldr r9, [%[a], #132]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24203,7 +23785,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #132]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+34] += m[34] * mu\n\t"
- "ldr r7, [%[m], #136]\n\t"
+ "ldr r7, [%[m], #136]\n\t"
"ldr r9, [%[a], #136]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24212,7 +23794,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #136]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+35] += m[35] * mu\n\t"
- "ldr r7, [%[m], #140]\n\t"
+ "ldr r7, [%[m], #140]\n\t"
"ldr r9, [%[a], #140]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24221,7 +23803,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #140]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+36] += m[36] * mu\n\t"
- "ldr r7, [%[m], #144]\n\t"
+ "ldr r7, [%[m], #144]\n\t"
"ldr r9, [%[a], #144]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24230,7 +23812,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #144]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+37] += m[37] * mu\n\t"
- "ldr r7, [%[m], #148]\n\t"
+ "ldr r7, [%[m], #148]\n\t"
"ldr r9, [%[a], #148]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24239,7 +23821,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #148]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+38] += m[38] * mu\n\t"
- "ldr r7, [%[m], #152]\n\t"
+ "ldr r7, [%[m], #152]\n\t"
"ldr r9, [%[a], #152]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24248,7 +23830,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #152]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+39] += m[39] * mu\n\t"
- "ldr r7, [%[m], #156]\n\t"
+ "ldr r7, [%[m], #156]\n\t"
"ldr r9, [%[a], #156]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24257,7 +23839,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #156]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+40] += m[40] * mu\n\t"
- "ldr r7, [%[m], #160]\n\t"
+ "ldr r7, [%[m], #160]\n\t"
"ldr r9, [%[a], #160]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24266,7 +23848,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #160]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+41] += m[41] * mu\n\t"
- "ldr r7, [%[m], #164]\n\t"
+ "ldr r7, [%[m], #164]\n\t"
"ldr r9, [%[a], #164]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24275,7 +23857,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #164]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+42] += m[42] * mu\n\t"
- "ldr r7, [%[m], #168]\n\t"
+ "ldr r7, [%[m], #168]\n\t"
"ldr r9, [%[a], #168]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24284,7 +23866,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #168]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+43] += m[43] * mu\n\t"
- "ldr r7, [%[m], #172]\n\t"
+ "ldr r7, [%[m], #172]\n\t"
"ldr r9, [%[a], #172]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24293,7 +23875,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #172]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+44] += m[44] * mu\n\t"
- "ldr r7, [%[m], #176]\n\t"
+ "ldr r7, [%[m], #176]\n\t"
"ldr r9, [%[a], #176]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24302,7 +23884,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #176]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+45] += m[45] * mu\n\t"
- "ldr r7, [%[m], #180]\n\t"
+ "ldr r7, [%[m], #180]\n\t"
"ldr r9, [%[a], #180]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24311,7 +23893,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #180]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+46] += m[46] * mu\n\t"
- "ldr r7, [%[m], #184]\n\t"
+ "ldr r7, [%[m], #184]\n\t"
"ldr r9, [%[a], #184]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24320,7 +23902,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #184]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+47] += m[47] * mu\n\t"
- "ldr r7, [%[m], #188]\n\t"
+ "ldr r7, [%[m], #188]\n\t"
"ldr r9, [%[a], #188]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24329,7 +23911,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #188]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+48] += m[48] * mu\n\t"
- "ldr r7, [%[m], #192]\n\t"
+ "ldr r7, [%[m], #192]\n\t"
"ldr r9, [%[a], #192]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24338,7 +23920,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #192]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+49] += m[49] * mu\n\t"
- "ldr r7, [%[m], #196]\n\t"
+ "ldr r7, [%[m], #196]\n\t"
"ldr r9, [%[a], #196]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24347,7 +23929,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #196]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+50] += m[50] * mu\n\t"
- "ldr r7, [%[m], #200]\n\t"
+ "ldr r7, [%[m], #200]\n\t"
"ldr r9, [%[a], #200]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24356,7 +23938,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #200]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+51] += m[51] * mu\n\t"
- "ldr r7, [%[m], #204]\n\t"
+ "ldr r7, [%[m], #204]\n\t"
"ldr r9, [%[a], #204]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24365,7 +23947,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #204]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+52] += m[52] * mu\n\t"
- "ldr r7, [%[m], #208]\n\t"
+ "ldr r7, [%[m], #208]\n\t"
"ldr r9, [%[a], #208]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24374,7 +23956,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #208]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+53] += m[53] * mu\n\t"
- "ldr r7, [%[m], #212]\n\t"
+ "ldr r7, [%[m], #212]\n\t"
"ldr r9, [%[a], #212]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24383,7 +23965,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #212]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+54] += m[54] * mu\n\t"
- "ldr r7, [%[m], #216]\n\t"
+ "ldr r7, [%[m], #216]\n\t"
"ldr r9, [%[a], #216]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24392,7 +23974,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #216]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+55] += m[55] * mu\n\t"
- "ldr r7, [%[m], #220]\n\t"
+ "ldr r7, [%[m], #220]\n\t"
"ldr r9, [%[a], #220]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24401,7 +23983,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #220]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+56] += m[56] * mu\n\t"
- "ldr r7, [%[m], #224]\n\t"
+ "ldr r7, [%[m], #224]\n\t"
"ldr r9, [%[a], #224]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24410,7 +23992,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #224]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+57] += m[57] * mu\n\t"
- "ldr r7, [%[m], #228]\n\t"
+ "ldr r7, [%[m], #228]\n\t"
"ldr r9, [%[a], #228]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24419,7 +24001,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #228]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+58] += m[58] * mu\n\t"
- "ldr r7, [%[m], #232]\n\t"
+ "ldr r7, [%[m], #232]\n\t"
"ldr r9, [%[a], #232]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24428,7 +24010,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #232]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+59] += m[59] * mu\n\t"
- "ldr r7, [%[m], #236]\n\t"
+ "ldr r7, [%[m], #236]\n\t"
"ldr r9, [%[a], #236]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24437,7 +24019,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #236]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+60] += m[60] * mu\n\t"
- "ldr r7, [%[m], #240]\n\t"
+ "ldr r7, [%[m], #240]\n\t"
"ldr r9, [%[a], #240]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24446,7 +24028,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #240]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+61] += m[61] * mu\n\t"
- "ldr r7, [%[m], #244]\n\t"
+ "ldr r7, [%[m], #244]\n\t"
"ldr r9, [%[a], #244]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24455,7 +24037,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #244]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+62] += m[62] * mu\n\t"
- "ldr r7, [%[m], #248]\n\t"
+ "ldr r7, [%[m], #248]\n\t"
"ldr r9, [%[a], #248]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24464,7 +24046,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #248]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+63] += m[63] * mu\n\t"
- "ldr r7, [%[m], #252]\n\t"
+ "ldr r7, [%[m], #252]\n\t"
"ldr r9, [%[a], #252]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24473,7 +24055,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #252]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+64] += m[64] * mu\n\t"
- "ldr r7, [%[m], #256]\n\t"
+ "ldr r7, [%[m], #256]\n\t"
"ldr r9, [%[a], #256]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24482,7 +24064,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #256]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+65] += m[65] * mu\n\t"
- "ldr r7, [%[m], #260]\n\t"
+ "ldr r7, [%[m], #260]\n\t"
"ldr r9, [%[a], #260]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24491,7 +24073,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #260]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+66] += m[66] * mu\n\t"
- "ldr r7, [%[m], #264]\n\t"
+ "ldr r7, [%[m], #264]\n\t"
"ldr r9, [%[a], #264]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24500,7 +24082,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #264]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+67] += m[67] * mu\n\t"
- "ldr r7, [%[m], #268]\n\t"
+ "ldr r7, [%[m], #268]\n\t"
"ldr r9, [%[a], #268]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24509,7 +24091,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #268]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+68] += m[68] * mu\n\t"
- "ldr r7, [%[m], #272]\n\t"
+ "ldr r7, [%[m], #272]\n\t"
"ldr r9, [%[a], #272]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24518,7 +24100,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #272]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+69] += m[69] * mu\n\t"
- "ldr r7, [%[m], #276]\n\t"
+ "ldr r7, [%[m], #276]\n\t"
"ldr r9, [%[a], #276]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24527,7 +24109,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #276]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+70] += m[70] * mu\n\t"
- "ldr r7, [%[m], #280]\n\t"
+ "ldr r7, [%[m], #280]\n\t"
"ldr r9, [%[a], #280]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24536,7 +24118,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #280]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+71] += m[71] * mu\n\t"
- "ldr r7, [%[m], #284]\n\t"
+ "ldr r7, [%[m], #284]\n\t"
"ldr r9, [%[a], #284]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24545,7 +24127,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #284]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+72] += m[72] * mu\n\t"
- "ldr r7, [%[m], #288]\n\t"
+ "ldr r7, [%[m], #288]\n\t"
"ldr r9, [%[a], #288]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24554,7 +24136,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #288]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+73] += m[73] * mu\n\t"
- "ldr r7, [%[m], #292]\n\t"
+ "ldr r7, [%[m], #292]\n\t"
"ldr r9, [%[a], #292]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24563,7 +24145,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #292]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+74] += m[74] * mu\n\t"
- "ldr r7, [%[m], #296]\n\t"
+ "ldr r7, [%[m], #296]\n\t"
"ldr r9, [%[a], #296]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24572,7 +24154,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #296]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+75] += m[75] * mu\n\t"
- "ldr r7, [%[m], #300]\n\t"
+ "ldr r7, [%[m], #300]\n\t"
"ldr r9, [%[a], #300]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24581,7 +24163,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #300]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+76] += m[76] * mu\n\t"
- "ldr r7, [%[m], #304]\n\t"
+ "ldr r7, [%[m], #304]\n\t"
"ldr r9, [%[a], #304]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24590,7 +24172,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #304]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+77] += m[77] * mu\n\t"
- "ldr r7, [%[m], #308]\n\t"
+ "ldr r7, [%[m], #308]\n\t"
"ldr r9, [%[a], #308]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24599,7 +24181,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #308]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+78] += m[78] * mu\n\t"
- "ldr r7, [%[m], #312]\n\t"
+ "ldr r7, [%[m], #312]\n\t"
"ldr r9, [%[a], #312]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24608,7 +24190,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #312]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+79] += m[79] * mu\n\t"
- "ldr r7, [%[m], #316]\n\t"
+ "ldr r7, [%[m], #316]\n\t"
"ldr r9, [%[a], #316]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24617,7 +24199,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #316]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+80] += m[80] * mu\n\t"
- "ldr r7, [%[m], #320]\n\t"
+ "ldr r7, [%[m], #320]\n\t"
"ldr r9, [%[a], #320]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24626,7 +24208,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #320]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+81] += m[81] * mu\n\t"
- "ldr r7, [%[m], #324]\n\t"
+ "ldr r7, [%[m], #324]\n\t"
"ldr r9, [%[a], #324]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24635,7 +24217,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #324]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+82] += m[82] * mu\n\t"
- "ldr r7, [%[m], #328]\n\t"
+ "ldr r7, [%[m], #328]\n\t"
"ldr r9, [%[a], #328]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24644,7 +24226,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #328]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+83] += m[83] * mu\n\t"
- "ldr r7, [%[m], #332]\n\t"
+ "ldr r7, [%[m], #332]\n\t"
"ldr r9, [%[a], #332]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24653,7 +24235,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #332]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+84] += m[84] * mu\n\t"
- "ldr r7, [%[m], #336]\n\t"
+ "ldr r7, [%[m], #336]\n\t"
"ldr r9, [%[a], #336]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24662,7 +24244,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #336]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+85] += m[85] * mu\n\t"
- "ldr r7, [%[m], #340]\n\t"
+ "ldr r7, [%[m], #340]\n\t"
"ldr r9, [%[a], #340]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24671,7 +24253,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #340]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+86] += m[86] * mu\n\t"
- "ldr r7, [%[m], #344]\n\t"
+ "ldr r7, [%[m], #344]\n\t"
"ldr r9, [%[a], #344]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24680,7 +24262,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #344]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+87] += m[87] * mu\n\t"
- "ldr r7, [%[m], #348]\n\t"
+ "ldr r7, [%[m], #348]\n\t"
"ldr r9, [%[a], #348]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24689,7 +24271,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #348]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+88] += m[88] * mu\n\t"
- "ldr r7, [%[m], #352]\n\t"
+ "ldr r7, [%[m], #352]\n\t"
"ldr r9, [%[a], #352]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24698,7 +24280,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #352]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+89] += m[89] * mu\n\t"
- "ldr r7, [%[m], #356]\n\t"
+ "ldr r7, [%[m], #356]\n\t"
"ldr r9, [%[a], #356]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24707,7 +24289,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #356]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+90] += m[90] * mu\n\t"
- "ldr r7, [%[m], #360]\n\t"
+ "ldr r7, [%[m], #360]\n\t"
"ldr r9, [%[a], #360]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24716,7 +24298,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #360]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+91] += m[91] * mu\n\t"
- "ldr r7, [%[m], #364]\n\t"
+ "ldr r7, [%[m], #364]\n\t"
"ldr r9, [%[a], #364]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24725,7 +24307,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #364]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+92] += m[92] * mu\n\t"
- "ldr r7, [%[m], #368]\n\t"
+ "ldr r7, [%[m], #368]\n\t"
"ldr r9, [%[a], #368]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24734,7 +24316,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #368]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+93] += m[93] * mu\n\t"
- "ldr r7, [%[m], #372]\n\t"
+ "ldr r7, [%[m], #372]\n\t"
"ldr r9, [%[a], #372]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24743,7 +24325,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #372]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+94] += m[94] * mu\n\t"
- "ldr r7, [%[m], #376]\n\t"
+ "ldr r7, [%[m], #376]\n\t"
"ldr r9, [%[a], #376]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24752,7 +24334,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #376]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+95] += m[95] * mu\n\t"
- "ldr r7, [%[m], #380]\n\t"
+ "ldr r7, [%[m], #380]\n\t"
"ldr r9, [%[a], #380]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24761,7 +24343,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #380]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+96] += m[96] * mu\n\t"
- "ldr r7, [%[m], #384]\n\t"
+ "ldr r7, [%[m], #384]\n\t"
"ldr r9, [%[a], #384]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24770,7 +24352,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #384]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+97] += m[97] * mu\n\t"
- "ldr r7, [%[m], #388]\n\t"
+ "ldr r7, [%[m], #388]\n\t"
"ldr r9, [%[a], #388]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24779,7 +24361,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #388]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+98] += m[98] * mu\n\t"
- "ldr r7, [%[m], #392]\n\t"
+ "ldr r7, [%[m], #392]\n\t"
"ldr r9, [%[a], #392]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24788,7 +24370,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #392]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+99] += m[99] * mu\n\t"
- "ldr r7, [%[m], #396]\n\t"
+ "ldr r7, [%[m], #396]\n\t"
"ldr r9, [%[a], #396]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24797,7 +24379,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #396]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+100] += m[100] * mu\n\t"
- "ldr r7, [%[m], #400]\n\t"
+ "ldr r7, [%[m], #400]\n\t"
"ldr r9, [%[a], #400]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24806,7 +24388,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #400]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+101] += m[101] * mu\n\t"
- "ldr r7, [%[m], #404]\n\t"
+ "ldr r7, [%[m], #404]\n\t"
"ldr r9, [%[a], #404]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24815,7 +24397,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #404]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+102] += m[102] * mu\n\t"
- "ldr r7, [%[m], #408]\n\t"
+ "ldr r7, [%[m], #408]\n\t"
"ldr r9, [%[a], #408]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24824,7 +24406,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #408]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+103] += m[103] * mu\n\t"
- "ldr r7, [%[m], #412]\n\t"
+ "ldr r7, [%[m], #412]\n\t"
"ldr r9, [%[a], #412]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24833,7 +24415,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #412]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+104] += m[104] * mu\n\t"
- "ldr r7, [%[m], #416]\n\t"
+ "ldr r7, [%[m], #416]\n\t"
"ldr r9, [%[a], #416]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24842,7 +24424,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #416]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+105] += m[105] * mu\n\t"
- "ldr r7, [%[m], #420]\n\t"
+ "ldr r7, [%[m], #420]\n\t"
"ldr r9, [%[a], #420]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24851,7 +24433,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #420]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+106] += m[106] * mu\n\t"
- "ldr r7, [%[m], #424]\n\t"
+ "ldr r7, [%[m], #424]\n\t"
"ldr r9, [%[a], #424]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24860,7 +24442,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #424]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+107] += m[107] * mu\n\t"
- "ldr r7, [%[m], #428]\n\t"
+ "ldr r7, [%[m], #428]\n\t"
"ldr r9, [%[a], #428]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24869,7 +24451,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #428]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+108] += m[108] * mu\n\t"
- "ldr r7, [%[m], #432]\n\t"
+ "ldr r7, [%[m], #432]\n\t"
"ldr r9, [%[a], #432]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24878,7 +24460,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #432]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+109] += m[109] * mu\n\t"
- "ldr r7, [%[m], #436]\n\t"
+ "ldr r7, [%[m], #436]\n\t"
"ldr r9, [%[a], #436]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24887,7 +24469,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #436]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+110] += m[110] * mu\n\t"
- "ldr r7, [%[m], #440]\n\t"
+ "ldr r7, [%[m], #440]\n\t"
"ldr r9, [%[a], #440]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24896,7 +24478,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #440]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+111] += m[111] * mu\n\t"
- "ldr r7, [%[m], #444]\n\t"
+ "ldr r7, [%[m], #444]\n\t"
"ldr r9, [%[a], #444]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24905,7 +24487,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #444]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+112] += m[112] * mu\n\t"
- "ldr r7, [%[m], #448]\n\t"
+ "ldr r7, [%[m], #448]\n\t"
"ldr r9, [%[a], #448]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24914,7 +24496,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #448]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+113] += m[113] * mu\n\t"
- "ldr r7, [%[m], #452]\n\t"
+ "ldr r7, [%[m], #452]\n\t"
"ldr r9, [%[a], #452]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24923,7 +24505,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #452]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+114] += m[114] * mu\n\t"
- "ldr r7, [%[m], #456]\n\t"
+ "ldr r7, [%[m], #456]\n\t"
"ldr r9, [%[a], #456]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24932,7 +24514,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #456]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+115] += m[115] * mu\n\t"
- "ldr r7, [%[m], #460]\n\t"
+ "ldr r7, [%[m], #460]\n\t"
"ldr r9, [%[a], #460]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24941,7 +24523,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #460]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+116] += m[116] * mu\n\t"
- "ldr r7, [%[m], #464]\n\t"
+ "ldr r7, [%[m], #464]\n\t"
"ldr r9, [%[a], #464]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24950,7 +24532,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #464]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+117] += m[117] * mu\n\t"
- "ldr r7, [%[m], #468]\n\t"
+ "ldr r7, [%[m], #468]\n\t"
"ldr r9, [%[a], #468]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24959,7 +24541,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #468]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+118] += m[118] * mu\n\t"
- "ldr r7, [%[m], #472]\n\t"
+ "ldr r7, [%[m], #472]\n\t"
"ldr r9, [%[a], #472]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24968,7 +24550,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #472]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+119] += m[119] * mu\n\t"
- "ldr r7, [%[m], #476]\n\t"
+ "ldr r7, [%[m], #476]\n\t"
"ldr r9, [%[a], #476]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24977,7 +24559,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #476]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+120] += m[120] * mu\n\t"
- "ldr r7, [%[m], #480]\n\t"
+ "ldr r7, [%[m], #480]\n\t"
"ldr r9, [%[a], #480]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24986,7 +24568,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #480]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+121] += m[121] * mu\n\t"
- "ldr r7, [%[m], #484]\n\t"
+ "ldr r7, [%[m], #484]\n\t"
"ldr r9, [%[a], #484]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -24995,7 +24577,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #484]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+122] += m[122] * mu\n\t"
- "ldr r7, [%[m], #488]\n\t"
+ "ldr r7, [%[m], #488]\n\t"
"ldr r9, [%[a], #488]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -25004,7 +24586,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #488]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+123] += m[123] * mu\n\t"
- "ldr r7, [%[m], #492]\n\t"
+ "ldr r7, [%[m], #492]\n\t"
"ldr r9, [%[a], #492]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -25013,7 +24595,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #492]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+124] += m[124] * mu\n\t"
- "ldr r7, [%[m], #496]\n\t"
+ "ldr r7, [%[m], #496]\n\t"
"ldr r9, [%[a], #496]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -25022,7 +24604,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #496]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+125] += m[125] * mu\n\t"
- "ldr r7, [%[m], #500]\n\t"
+ "ldr r7, [%[m], #500]\n\t"
"ldr r9, [%[a], #500]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -25031,7 +24613,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #500]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+126] += m[126] * mu\n\t"
- "ldr r7, [%[m], #504]\n\t"
+ "ldr r7, [%[m], #504]\n\t"
"ldr r9, [%[a], #504]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -25062,7 +24644,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - ca);
@@ -25077,8 +24659,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_128(r, a, b);
sp_4096_mont_reduce_128(r, m, mp);
@@ -25091,8 +24673,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_128(r, a);
sp_4096_mont_reduce_128(r, m, mp);
@@ -26782,7 +26364,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -26848,34 +26431,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -26927,7 +26510,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -27009,34 +26593,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -27081,11 +26665,13 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[256], m[128], r[256];
+ sp_digit a[256];
+ sp_digit m[128];
+ sp_digit r[256];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -27588,9 +27174,9 @@ static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -27654,8 +27240,11 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[128 * 2];
- sp_digit p[64], q[64], dp[64];
- sp_digit tmpa[128], tmpb[128];
+ sp_digit p[64];
+ sp_digit q[64];
+ sp_digit dp[64];
+ sp_digit tmpa[128];
+ sp_digit tmpb[128];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -27752,7 +27341,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -27775,17 +27364,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 128;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -27798,14 +27389,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -27832,10 +27425,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -28670,10 +28266,12 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -28708,34 +28306,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_4096_lshift_128(r, norm, (byte)y);
+ sp_4096_lshift_128(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -28746,7 +28344,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_4096_mont_sqr_128(r, r, m, mp);
sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_lshift_128(r, r, (byte)y);
+ sp_4096_lshift_128(r, r, y);
sp_4096_mul_d_128(tmp, norm, r[128]);
r[128] = 0;
o = sp_4096_add_128(r, r, tmp);
@@ -28782,11 +28380,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
word32 i;
@@ -28821,6 +28421,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -28833,19 +28434,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 8];
+ /* Y ordinate of point. */
sp_digit y[2 * 8];
+ /* Z ordinate of point. */
sp_digit z[2 * 8];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -28915,7 +28520,1143 @@ static const sp_digit p256_b[8] = {
};
#endif
-static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p)
+#ifdef WOLFSSL_SP_SMALL
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #64\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #0\n\t"
+ "mov r7, #0\n\t"
+ "mov r8, #0\n\t"
+ "\n1:\n\t"
+ "subs r3, r5, #28\n\t"
+ "it cc\n\t"
+ "movcc r3, #0\n\t"
+ "sub r4, r5, r3\n\t"
+ "\n2:\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "ldr r12, [%[b], r4]\n\t"
+ "umull r9, r10, r14, r12\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, #0\n\t"
+ "add r3, r3, #4\n\t"
+ "sub r4, r4, #4\n\t"
+ "cmp r3, #32\n\t"
+ "beq 3f\n\t"
+ "cmp r3, r5\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "str r6, [sp, r5]\n\t"
+ "mov r6, r7\n\t"
+ "mov r7, r8\n\t"
+ "mov r8, #0\n\t"
+ "add r5, r5, #4\n\t"
+ "cmp r5, #56\n\t"
+ "ble 1b\n\t"
+ "str r6, [sp, r5]\n\t"
+ "\n4:\n\t"
+ "ldr r6, [sp, #0]\n\t"
+ "ldr r7, [sp, #4]\n\t"
+ "ldr r8, [sp, #8]\n\t"
+ "ldr r3, [sp, #12]\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "str r8, [%[r], #8]\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "add sp, sp, #16\n\t"
+ "add %[r], %[r], #16\n\t"
+ "subs r5, r5, #16\n\t"
+ "bgt 4b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+#else
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #32\n\t"
+ "mov r10, #0\n\t"
+ "# A[0] * B[0]\n\t"
+ "ldr r11, [%[a], #0]\n\t"
+ "ldr r12, [%[b], #0]\n\t"
+ "umull r3, r4, r11, r12\n\t"
+ "mov r5, #0\n\t"
+ "str r3, [sp]\n\t"
+ "# A[0] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[1] * B[0]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #4]\n\t"
+ "# A[2] * B[0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[1]\n\t"
+ "ldr r11, [%[a], #4]\n\t"
+ "ldr r12, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[2]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #8]\n\t"
+ "# A[0] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[1] * B[2]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[1]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[0]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #12]\n\t"
+ "# A[4] * B[0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[3] * B[1]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[2]\n\t"
+ "ldr r11, [%[a], #8]\n\t"
+ "ldr r12, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[3]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[0] * B[4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #16]\n\t"
+ "# A[0] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[4]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[2]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[1]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[0]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #20]\n\t"
+ "# A[6] * B[0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[5] * B[1]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[2]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[3]\n\t"
+ "ldr r11, [%[a], #12]\n\t"
+ "ldr r12, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[4]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[1] * B[5]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[0] * B[6]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #24]\n\t"
+ "# A[0] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[1] * B[6]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[5]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[4]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[3]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[2]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[1]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[0]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #28]\n\t"
+ "# A[7] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[6] * B[2]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[3]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[4]\n\t"
+ "ldr r11, [%[a], #16]\n\t"
+ "ldr r12, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[5]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[6]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[1] * B[7]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #32]\n\t"
+ "# A[2] * B[7]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[3] * B[6]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[4]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[3]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[7] * B[2]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #36]\n\t"
+ "# A[7] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[6] * B[4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[5]\n\t"
+ "ldr r11, [%[a], #20]\n\t"
+ "ldr r12, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[6]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[7]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "# A[4] * B[7]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[5] * B[6]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[5]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[4]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "# A[7] * B[5]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[6] * B[6]\n\t"
+ "ldr r11, [%[a], #24]\n\t"
+ "ldr r12, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[7]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #48]\n\t"
+ "# A[6] * B[7]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[7] * B[6]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "# A[7] * B[7]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r5, [%[r], #56]\n\t"
+ "str r3, [%[r], #60]\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "sub %[r], %[r], #32\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+ );
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #64\n\t"
+ "mov r12, #0\n\t"
+ "mov r6, #0\n\t"
+ "mov r7, #0\n\t"
+ "mov r8, #0\n\t"
+ "mov r5, #0\n\t"
+ "\n1:\n\t"
+ "subs r3, r5, #28\n\t"
+ "it cc\n\t"
+ "movcc r3, r12\n\t"
+ "sub r4, r5, r3\n\t"
+ "\n2:\n\t"
+ "cmp r4, r3\n\t"
+ "beq 4f\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "ldr r9, [%[a], r4]\n\t"
+ "umull r9, r10, r14, r9\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "umull r9, r10, r14, r14\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "\n5:\n\t"
+ "add r3, r3, #4\n\t"
+ "sub r4, r4, #4\n\t"
+ "cmp r3, #32\n\t"
+ "beq 3f\n\t"
+ "cmp r3, r4\n\t"
+ "bgt 3f\n\t"
+ "cmp r3, r5\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "str r6, [sp, r5]\n\t"
+ "mov r6, r7\n\t"
+ "mov r7, r8\n\t"
+ "mov r8, #0\n\t"
+ "add r5, r5, #4\n\t"
+ "cmp r5, #56\n\t"
+ "ble 1b\n\t"
+ "str r6, [sp, r5]\n\t"
+ "\n4:\n\t"
+ "ldr r6, [sp, #0]\n\t"
+ "ldr r7, [sp, #4]\n\t"
+ "ldr r8, [sp, #8]\n\t"
+ "ldr r3, [sp, #12]\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "str r8, [%[r], #8]\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "add sp, sp, #16\n\t"
+ "add %[r], %[r], #16\n\t"
+ "subs r5, r5, #16\n\t"
+ "bgt 4b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
+ );
+}
+
+#else
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #32\n\t"
+ "mov r12, #0\n\t"
+ "# A[0] * A[0]\n\t"
+ "ldr r10, [%[a], #0]\n\t"
+ "umull r8, r3, r10, r10\n\t"
+ "mov r4, #0\n\t"
+ "str r8, [sp]\n\t"
+ "# A[0] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #4]\n\t"
+ "# A[0] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[1] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [sp, #8]\n\t"
+ "# A[0] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[1] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [sp, #12]\n\t"
+ "# A[0] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[1] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[2] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #16]\n\t"
+ "# A[0] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #20]\n\t"
+ "# A[0] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #24]\n\t"
+ "# A[0] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #28]\n\t"
+ "# A[1] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[2] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "# A[2] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[3] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #36]\n\t"
+ "# A[3] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[4] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[5] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [%[r], #40]\n\t"
+ "# A[4] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[5] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "# A[5] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[6] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [%[r], #48]\n\t"
+ "# A[6] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [%[r], #52]\n\t"
+ "# A[7] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adc r2, r2, r9\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r2, [%[r], #60]\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "sub %[r], %[r], #32\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12"
+ );
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #32\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], #-1\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "mov r4, #0\n\t"
+ "adc %[c], r4, #0\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "ldr r10, [%[b], #8]\n\t"
+ "ldr r14, [%[b], #12]\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "ldr r10, [%[b], #24]\n\t"
+ "ldr r14, [%[b], #28]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "adc %[c], r12, r12\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #32\n\t"
+ "\n1:\n\t"
+ "rsbs %[c], %[c], #0\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "sbc %[c], r4, r4\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r3, [%[a], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r7, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "ldr r10, [%[b], #12]\n\t"
+ "subs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #0]\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[a], #24]\n\t"
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r7, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "ldr r10, [%[b], #28]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "str r5, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ "sbc %[c], %[c], #0\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp,
+ sp_point_256** p)
{
int ret = MP_OKAY;
(void)heap;
@@ -28940,6 +29681,12 @@ static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p)
#endif
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -28952,7 +29699,7 @@ static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
}
#else
/* Clear point data if requested. */
- if (clear != 0) {
+ if ((p != NULL) && (clear != 0)) {
XMEMSET(p, 0, sizeof(*p));
}
#endif
@@ -29211,7 +29958,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -29245,7 +29993,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -29281,7 +30031,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
* p Point of type sp_point_256 (result).
* pm Point of type ecc_point.
*/
-static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm)
+static void sp_256_point_from_ecc_point_8(sp_point_256* p,
+ const ecc_point* pm)
{
XMEMSET(p->x, 0, sizeof(p->x));
XMEMSET(p->y, 0, sizeof(p->y));
@@ -29308,17 +30059,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = 8;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 8; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -29331,14 +30084,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 8; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -30571,7 +31326,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint32_t p256_mod_minus_2[8] = {
@@ -30894,6 +31649,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -30902,13 +31658,12 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -30916,7 +31671,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -30924,7 +31679,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -30933,7 +31688,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -30942,7 +31697,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -30951,7 +31706,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -30982,7 +31737,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca);
@@ -30994,7 +31749,8 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_8(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*8;
@@ -31030,106 +31786,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "add r12, %[a], #32\n\t"
- "\n1:\n\t"
- "adds %[c], %[c], #-1\n\t"
- "ldr r4, [%[a]], #4\n\t"
- "ldr r5, [%[a]], #4\n\t"
- "ldr r6, [%[a]], #4\n\t"
- "ldr r7, [%[a]], #4\n\t"
- "ldr r8, [%[b]], #4\n\t"
- "ldr r9, [%[b]], #4\n\t"
- "ldr r10, [%[b]], #4\n\t"
- "ldr r14, [%[b]], #4\n\t"
- "adcs r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r]], #4\n\t"
- "str r5, [%[r]], #4\n\t"
- "str r6, [%[r]], #4\n\t"
- "str r7, [%[r]], #4\n\t"
- "mov r4, #0\n\t"
- "adc %[c], r4, #0\n\t"
- "cmp %[a], r12\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r12, #0\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[a], #8]\n\t"
- "ldr r7, [%[a], #12]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "ldr r10, [%[b], #8]\n\t"
- "ldr r14, [%[b], #12]\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "str r6, [%[r], #8]\n\t"
- "str r7, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[a], #24]\n\t"
- "ldr r7, [%[a], #28]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "ldr r10, [%[b], #24]\n\t"
- "ldr r14, [%[b], #28]\n\t"
- "adcs r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "str r6, [%[r], #24]\n\t"
- "str r7, [%[r], #28]\n\t"
- "adc %[c], r12, r12\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -31687,104 +32343,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d
sp_256_mont_sub_8(y, y, t2, p256_mod);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "add r12, %[a], #32\n\t"
- "\n1:\n\t"
- "rsbs %[c], %[c], #0\n\t"
- "ldr r4, [%[a]], #4\n\t"
- "ldr r5, [%[a]], #4\n\t"
- "ldr r6, [%[a]], #4\n\t"
- "ldr r7, [%[a]], #4\n\t"
- "ldr r8, [%[b]], #4\n\t"
- "ldr r9, [%[b]], #4\n\t"
- "ldr r10, [%[b]], #4\n\t"
- "ldr r14, [%[b]], #4\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "sbcs r7, r7, r14\n\t"
- "str r4, [%[r]], #4\n\t"
- "str r5, [%[r]], #4\n\t"
- "str r6, [%[r]], #4\n\t"
- "str r7, [%[r]], #4\n\t"
- "sbc %[c], r4, r4\n\t"
- "cmp %[a], r12\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[a], #8]\n\t"
- "ldr r6, [%[a], #12]\n\t"
- "ldr r7, [%[b], #0]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "ldr r10, [%[b], #12]\n\t"
- "subs r3, r3, r7\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[a], #24]\n\t"
- "ldr r6, [%[a], #28]\n\t"
- "ldr r7, [%[b], #16]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "ldr r10, [%[b], #28]\n\t"
- "sbcs r3, r3, r7\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "sbc %[c], %[c], #0\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Compare two numbers to determine if they are equal.
* Constant time implementation.
*
@@ -32008,8 +32566,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_8(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -32164,9 +32722,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 256 doubles.
+ * 76 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -32195,7 +32755,8 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -32268,7 +32829,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
i = 6;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_256_get_point_16_8(rt, t, y);
@@ -32333,12 +32894,6 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_256 {
- sp_digit x[8];
- sp_digit y[8];
-} sp_table_entry_256;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -32347,7 +32902,8 @@ typedef struct sp_table_entry_256 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*8;
@@ -32428,6 +32984,36 @@ static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t)
sp_256_div2_8(y, y, p256_mod);
}
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 8;
+ sp_digit* tmp = t + 4 * 8;
+
+ sp_256_mont_inv_8(t1, a->z, tmp);
+
+ sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
+ sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
+
+ sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
+ sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
+ XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
+}
+
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_256 {
+ sp_digit x[8];
+ sp_digit y[8];
+} sp_table_entry_256;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -32513,29 +33099,11 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a Point to convert.
- * t Temporary data.
- */
-static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
-{
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2 * 8;
- sp_digit* tmp = t + 4 * 8;
-
- sp_256_mont_inv_8(t1, a->z, tmp);
-
- sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
-
- sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
- XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 64 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -32546,12 +33114,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -32670,8 +33241,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -32693,8 +33266,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -32722,8 +33297,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=63; j<4; j++,x+=64) {
+ x = 63;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -32737,8 +33314,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=62; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=64) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -32780,16 +33359,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -32797,9 +33385,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -32908,6 +33502,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 32 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -32918,12 +33516,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -33042,8 +33643,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -33065,8 +33668,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -33094,8 +33699,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=31; j<8; j++,x+=32) {
+ x = 31;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -33109,8 +33716,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=30; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=32) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -33152,16 +33761,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -33169,9 +33787,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -33288,8 +33912,8 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -33330,7 +33954,94 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(point, gm);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 64 between points.
+ */
static const sp_table_entry_256 p256_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -33415,6 +34126,11 @@ static const sp_table_entry_256 p256_table[16] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -33430,6 +34146,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 32 between points.
+ */
static const sp_table_entry_256 p256_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -34714,6 +35434,11 @@ static const sp_table_entry_256 p256_table[256] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -34739,7 +35464,7 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -34780,6 +35505,87 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P256 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -34793,7 +35599,7 @@ static int sp_256_iszero_8(const sp_digit* a)
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -34840,7 +35646,8 @@ static void sp_256_add_one_8(sp_digit* a)
*/
static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -34984,7 +35791,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_256_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 256 / 8 - 1;
a[j] = 0;
@@ -35025,7 +35835,7 @@ static void sp_256_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -35076,564 +35886,6 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
#endif /* HAVE_ECC_DHE */
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #64\n\t"
- "mov r5, #0\n\t"
- "mov r6, #0\n\t"
- "mov r7, #0\n\t"
- "mov r8, #0\n\t"
- "\n1:\n\t"
- "subs r3, r5, #28\n\t"
- "it cc\n\t"
- "movcc r3, #0\n\t"
- "sub r4, r5, r3\n\t"
- "\n2:\n\t"
- "ldr r14, [%[a], r3]\n\t"
- "ldr r12, [%[b], r4]\n\t"
- "umull r9, r10, r14, r12\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, #0\n\t"
- "add r3, r3, #4\n\t"
- "sub r4, r4, #4\n\t"
- "cmp r3, #32\n\t"
- "beq 3f\n\t"
- "cmp r3, r5\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "str r6, [sp, r5]\n\t"
- "mov r6, r7\n\t"
- "mov r7, r8\n\t"
- "mov r8, #0\n\t"
- "add r5, r5, #4\n\t"
- "cmp r5, #56\n\t"
- "ble 1b\n\t"
- "str r6, [sp, r5]\n\t"
- "\n4:\n\t"
- "ldr r6, [sp, #0]\n\t"
- "ldr r7, [sp, #4]\n\t"
- "ldr r8, [sp, #8]\n\t"
- "ldr r3, [sp, #12]\n\t"
- "str r6, [%[r], #0]\n\t"
- "str r7, [%[r], #4]\n\t"
- "str r8, [%[r], #8]\n\t"
- "str r3, [%[r], #12]\n\t"
- "add sp, sp, #16\n\t"
- "add %[r], %[r], #16\n\t"
- "subs r5, r5, #16\n\t"
- "bgt 4b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #32\n\t"
- "mov r10, #0\n\t"
- "# A[0] * B[0]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r3, r4, r8, r9\n\t"
- "mov r5, #0\n\t"
- "str r3, [sp]\n\t"
- "# A[0] * B[1]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r10, r10\n\t"
- "# A[1] * B[0]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "str r4, [sp, #4]\n\t"
- "# A[0] * B[2]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[1] * B[1]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[0]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "str r5, [sp, #8]\n\t"
- "# A[0] * B[3]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r10, r10\n\t"
- "# A[1] * B[2]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[2] * B[1]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[3] * B[0]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "str r3, [sp, #12]\n\t"
- "# A[0] * B[4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r10, r10\n\t"
- "# A[1] * B[3]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[2] * B[2]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[1]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[0]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "str r4, [sp, #16]\n\t"
- "# A[0] * B[5]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[1] * B[4]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[3]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[3] * B[2]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[4] * B[1]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[0]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "str r5, [sp, #20]\n\t"
- "# A[0] * B[6]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r10, r10\n\t"
- "# A[1] * B[5]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[2] * B[4]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[3] * B[3]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[4] * B[2]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[1]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[0]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "str r3, [sp, #24]\n\t"
- "# A[0] * B[7]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r10, r10\n\t"
- "# A[1] * B[6]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[2] * B[5]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[4]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[3]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[5] * B[2]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[6] * B[1]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[7] * B[0]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "str r4, [sp, #28]\n\t"
- "# A[1] * B[7]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[2] * B[6]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[3] * B[5]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[4] * B[4]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[3]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[6] * B[2]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[7] * B[1]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "str r5, [%[r], #32]\n\t"
- "# A[2] * B[7]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r10, r10\n\t"
- "# A[3] * B[6]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[4] * B[5]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[4]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[3]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[7] * B[2]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "str r3, [%[r], #36]\n\t"
- "# A[3] * B[7]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r10, r10\n\t"
- "# A[4] * B[6]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[5] * B[5]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[6] * B[4]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[7] * B[3]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "str r4, [%[r], #40]\n\t"
- "# A[4] * B[7]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[5] * B[6]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[6] * B[5]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[7] * B[4]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "str r5, [%[r], #44]\n\t"
- "# A[5] * B[7]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r10, r10\n\t"
- "# A[6] * B[6]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[7] * B[5]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "str r3, [%[r], #48]\n\t"
- "# A[6] * B[7]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r10, r10\n\t"
- "# A[7] * B[6]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "str r4, [%[r], #52]\n\t"
- "# A[7] * B[7]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r5, [%[r], #56]\n\t"
- "str r3, [%[r], #60]\n\t"
- "ldr r3, [sp, #0]\n\t"
- "ldr r4, [sp, #4]\n\t"
- "ldr r5, [sp, #8]\n\t"
- "ldr r6, [sp, #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [sp, #16]\n\t"
- "ldr r4, [sp, #20]\n\t"
- "ldr r5, [sp, #24]\n\t"
- "ldr r6, [sp, #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "add sp, sp, #32\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
- );
-}
-
-#endif /* WOLFSSL_SP_SMALL */
#endif
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
#ifdef WOLFSSL_SP_SMALL
@@ -35778,51 +36030,45 @@ static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
@@ -35981,435 +36227,6 @@ static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit
#endif
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #64\n\t"
- "mov r12, #0\n\t"
- "mov r6, #0\n\t"
- "mov r7, #0\n\t"
- "mov r8, #0\n\t"
- "mov r5, #0\n\t"
- "\n1:\n\t"
- "subs r3, r5, #28\n\t"
- "it cc\n\t"
- "movcc r3, r12\n\t"
- "sub r4, r5, r3\n\t"
- "\n2:\n\t"
- "cmp r4, r3\n\t"
- "beq 4f\n\t"
- "ldr r14, [%[a], r3]\n\t"
- "ldr r9, [%[a], r4]\n\t"
- "umull r9, r10, r14, r9\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "ldr r14, [%[a], r3]\n\t"
- "umull r9, r10, r14, r14\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "\n5:\n\t"
- "add r3, r3, #4\n\t"
- "sub r4, r4, #4\n\t"
- "cmp r3, #32\n\t"
- "beq 3f\n\t"
- "cmp r3, r4\n\t"
- "bgt 3f\n\t"
- "cmp r3, r5\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "str r6, [sp, r5]\n\t"
- "mov r6, r7\n\t"
- "mov r7, r8\n\t"
- "mov r8, #0\n\t"
- "add r5, r5, #4\n\t"
- "cmp r5, #56\n\t"
- "ble 1b\n\t"
- "str r6, [sp, r5]\n\t"
- "\n4:\n\t"
- "ldr r6, [sp, #0]\n\t"
- "ldr r7, [sp, #4]\n\t"
- "ldr r8, [sp, #8]\n\t"
- "ldr r3, [sp, #12]\n\t"
- "str r6, [%[r], #0]\n\t"
- "str r7, [%[r], #4]\n\t"
- "str r8, [%[r], #8]\n\t"
- "str r3, [%[r], #12]\n\t"
- "add sp, sp, #16\n\t"
- "add %[r], %[r], #16\n\t"
- "subs r5, r5, #16\n\t"
- "bgt 4b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
- );
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #32\n\t"
- "mov r14, #0\n\t"
- "# A[0] * A[0]\n\t"
- "ldr r10, [%[a], #0]\n\t"
- "umull r8, r3, r10, r10\n\t"
- "mov r4, #0\n\t"
- "str r8, [sp]\n\t"
- "# A[0] * A[1]\n\t"
- "ldr r10, [%[a], #4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [sp, #4]\n\t"
- "# A[0] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "# A[1] * A[1]\n\t"
- "ldr r10, [%[a], #4]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "str r4, [sp, #8]\n\t"
- "# A[0] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "# A[1] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "str r2, [sp, #12]\n\t"
- "# A[0] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[1] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[2] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [sp, #16]\n\t"
- "# A[0] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [sp, #20]\n\t"
- "# A[0] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [sp, #24]\n\t"
- "# A[0] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r2, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r3, r3, r5\n\t"
- "adcs r4, r4, r6\n\t"
- "adc r2, r2, r7\n\t"
- "str r3, [sp, #28]\n\t"
- "# A[1] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[2] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [%[r], #32]\n\t"
- "# A[2] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[3] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [%[r], #36]\n\t"
- "# A[3] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[4] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[5] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [%[r], #40]\n\t"
- "# A[4] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "# A[5] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "str r4, [%[r], #44]\n\t"
- "# A[5] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "# A[6] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "str r2, [%[r], #48]\n\t"
- "# A[6] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [%[r], #52]\n\t"
- "# A[7] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r4, r4, r8\n\t"
- "adc r2, r2, r9\n\t"
- "str r4, [%[r], #56]\n\t"
- "str r2, [%[r], #60]\n\t"
- "ldr r2, [sp, #0]\n\t"
- "ldr r3, [sp, #4]\n\t"
- "ldr r4, [sp, #8]\n\t"
- "ldr r8, [sp, #12]\n\t"
- "str r2, [%[r], #0]\n\t"
- "str r3, [%[r], #4]\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r8, [%[r], #12]\n\t"
- "ldr r2, [sp, #16]\n\t"
- "ldr r3, [sp, #20]\n\t"
- "ldr r4, [sp, #24]\n\t"
- "ldr r8, [sp, #28]\n\t"
- "str r2, [%[r], #16]\n\t"
- "str r3, [%[r], #20]\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r8, [%[r], #28]\n\t"
- "add sp, sp, #32\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
- );
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
/* Order-2 for the P256 curve. */
static const uint32_t p256_order_minus_2[8] = {
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU,
@@ -36417,7 +36234,7 @@ static const uint32_t p256_order_minus_2[8] = {
};
#else
/* The low half of the order-2 of the P256 curve. */
-static const uint32_t p256_order_low[4] = {
+static const sp_int_digit p256_order_low[4] = {
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
};
#endif /* WOLFSSL_SP_SMALL */
@@ -36563,7 +36380,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6 */
for (i=127; i>=112; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -36573,7 +36390,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
for (i=107; i>=64; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -36583,7 +36400,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
for (i=59; i>=32; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -36593,7 +36410,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
for (i=27; i>=0; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -36604,12 +36421,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_256_mul_8(k, k, p256_norm_order);
+ err = sp_256_mod_8(k, k, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(k);
+
+ /* kInv = 1/k mod order */
+ sp_256_mont_inv_order_8(kInv, k, tmp);
+ sp_256_norm_8(kInv);
+
+ /* s = r * x + e */
+ sp_256_mul_8(x, x, r);
+ err = sp_256_mod_8(x, x, p256_order);
+ }
+ if (err == MP_OKAY) {
+ sp_256_norm_8(x);
+ carry = sp_256_add_8(s, e, x);
+ sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
+ sp_256_norm_8(s);
+ c = sp_256_cmp_8(s, p256_order);
+ sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
+ sp_256_norm_8(s);
+
+ /* s = s * k^-1 mod order */
+ sp_256_mont_mul_order_8(s, s, kInv);
+ sp_256_norm_8(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 256 bits] from binary
* r = (k.G)->x mod order
@@ -36644,8 +36512,8 @@ typedef struct sp_ecc_sign_256_ctx {
int i;
} sp_ecc_sign_256_ctx;
-int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
@@ -36785,8 +36653,8 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -36804,11 +36672,9 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_256* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -36839,7 +36705,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 32U) {
hashLen = 32U;
@@ -36847,8 +36712,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_256_from_mp(x, 8, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
@@ -36858,7 +36721,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL);
+ err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -36869,38 +36732,15 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0));
sp_256_norm_8(r);
- /* Conv k to Montgomery form (mod order) */
- sp_256_mul_8(k, k, p256_norm_order);
- err = sp_256_mod_8(k, k, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(k);
- /* kInv = 1/k mod order */
- sp_256_mont_inv_order_8(kInv, k, tmp);
- sp_256_norm_8(kInv);
-
- /* s = r * x + e */
- sp_256_mul_8(x, x, r);
- err = sp_256_mod_8(x, x, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(x);
+ sp_256_from_mp(x, 8, priv);
sp_256_from_bin(e, 8, hash, (int)hashLen);
- carry = sp_256_add_8(s, e, x);
- sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
- sp_256_norm_8(s);
- c = sp_256_cmp_8(s, p256_order);
- sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
- sp_256_norm_8(s);
- /* s = s * k^-1 mod order */
- sp_256_mont_mul_order_8(s, s, kInv);
- sp_256_norm_8(s);
+ err = sp_256_calc_s_8(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_256_iszero_8(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -36928,7 +36768,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U);
#endif
sp_256_point_free_8(point, 1, heap);
@@ -37224,6 +37063,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2,
+ sp_digit* tmp)
+{
+
+ sp_256_proj_point_add_8(p1, p1, p2, tmp);
+ if (sp_256_iszero_8(p1->z)) {
+ if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
+ sp_256_proj_point_dbl_8(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_256_mod_inv_8(s, s, p256_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_256_mul_8(s, s, p256_norm_order);
+ }
+ err = sp_256_mod_8(s, s, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_256_mont_inv_order_8(s, s, tmp);
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#else
+ {
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_256_add_points_8(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 256)
@@ -37242,8 +37171,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_256_ctx {
@@ -37262,8 +37190,9 @@ typedef struct sp_ecc_verify_256_ctx {
sp_point_256 p2;
} sp_ecc_verify_256_ctx;
-int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
@@ -37417,8 +37346,9 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -37437,7 +37367,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_256* p1;
sp_point_256* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_256_point_new_8(heap, p1d, p1);
@@ -37478,66 +37408,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_256_mod_inv_8(s, s, p256_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_256_mul_8(s, s, p256_norm_order);
- }
- err = sp_256_mod_8(s, s, p256_order);
+ err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_256_norm_8(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_256_mont_inv_order_8(s, s, tmp);
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#else
- {
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_256_proj_point_add_8(p1, p1, p2, tmp);
- if (sp_256_iszero_8(p1->z)) {
- if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
- sp_256_proj_point_dbl_8(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_256_from_mp(u2, 8, r);
@@ -37559,16 +37432,16 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_256_cmp_8(u2, p256_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
- p256_mp_mod);
- *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
+ p256_mp_mod);
+ *res = (sp_256_cmp_8(p1->x, u1) == 0);
}
}
}
@@ -37592,7 +37465,8 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
+static int sp_256_ecc_is_point_8(const sp_point_256* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -37655,7 +37529,7 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 pubd;
@@ -37689,7 +37563,8 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[8];
@@ -37743,12 +37618,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_256_cmp_8(pub->x, p256_mod) >= 0 ||
- sp_256_cmp_8(pub->y, p256_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(pub->x, p256_mod) >= 0) ||
+ (sp_256_cmp_8(pub->y, p256_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -37760,12 +37634,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_256_iszero_8(p->x) == 0) ||
- (sp_256_iszero_8(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) ||
+ (sp_256_iszero_8(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -37773,12 +37645,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_256_cmp_8(p->x, pub->x) != 0 ||
- sp_256_cmp_8(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(p->x, pub->x) != 0) ||
+ (sp_256_cmp_8(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -37968,7 +37839,7 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_256_from_mp(p->y, 8, pY);
sp_256_from_mp(p->z, 8, pZ);
- sp_256_map_8(p, p, tmp);
+ sp_256_map_8(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -38148,9 +38019,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
/* Point structure to use. */
typedef struct sp_point_384 {
+ /* X ordinate of point. */
sp_digit x[2 * 12];
+ /* Y ordinate of point. */
sp_digit y[2 * 12];
+ /* Z ordinate of point. */
sp_digit z[2 * 12];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_384;
@@ -38220,336 +38095,6 @@ static const sp_digit p384_b[12] = {
};
#endif
-static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
-#endif
-
-
-static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- int64_t* t;
-#else
- int64_t t[12];
-#endif
- int64_t o;
- int err = MP_OKAY;
-
- (void)m;
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
- if (t == NULL) {
- err = MEMORY_E;
- }
-#endif
-
- if (err == MP_OKAY) {
- /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
- t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11];
- /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
- t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
- t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11];
- /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
- t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11];
- /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
- t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11];
- /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
- t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
- t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11];
- /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
- t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11];
- /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
- t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8];
- /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
- t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9];
- /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
- t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10];
- /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
- t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11];
-
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
- o = t[11] >> 32; t[11] &= 0xffffffff;
- t[0] += o;
- t[1] -= o;
- t[3] += o;
- t[4] += o;
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
-
- r[0] = t[0];
- r[1] = t[1];
- r[2] = t[2];
- r[3] = t[3];
- r[4] = t[4];
- r[5] = t[5];
- r[6] = t[6];
- r[7] = t[7];
- r[8] = t[8];
- r[9] = t[9];
- r[10] = t[10];
- r[11] = t[11];
- }
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- if (t != NULL)
- XFREE(t, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
- return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 32
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_384.
- *
- * p Point of type sp_point_384 (result).
- * pm Point of type ecc_point.
- */
-static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_384_from_mp(p->x, 12, pm->x);
- sp_384_from_mp(p->y, 12, pm->y);
- sp_384_from_mp(p->z, 12, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_384_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
- r->used = 12;
- mp_clamp(r);
-#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 32 - s;
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_384 to type ecc_point.
- *
- * p Point of type sp_point_384.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
-{
- int err;
-
- err = sp_384_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
#ifdef WOLFSSL_SP_SMALL
/* Multiply a and b into r. (r = a * b)
*
@@ -38624,66 +38169,60 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"sub sp, sp, #48\n\t"
"mov r10, #0\n\t"
"# A[0] * B[0]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r3, r4, r8, r9\n\t"
+ "ldr r11, [%[a], #0]\n\t"
+ "ldr r12, [%[b], #0]\n\t"
+ "umull r3, r4, r11, r12\n\t"
"mov r5, #0\n\t"
"str r3, [sp]\n\t"
"# A[0] * B[1]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[1] * B[0]\n\t"
"ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #4]\n\t"
+ "# A[2] * B[0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[1]\n\t"
+ "ldr r11, [%[a], #4]\n\t"
+ "ldr r12, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[0] * B[2]\n\t"
"ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[1] * B[1]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[0]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #0]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #8]\n\t"
"# A[0] * B[3]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
"# A[1] * B[2]\n\t"
- "ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[2] * B[1]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -38695,13 +38234,25 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #12]\n\t"
- "# A[0] * B[4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[4] * B[0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
+ "# A[3] * B[1]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[2]\n\t"
+ "ldr r11, [%[a], #8]\n\t"
+ "ldr r12, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[1] * B[3]\n\t"
"ldr r8, [%[a], #4]\n\t"
"ldr r9, [%[b], #12]\n\t"
@@ -38709,30 +38260,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[2] * B[2]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[1]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[0]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #16]\n\t"
"# A[0] * B[5]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
@@ -38746,16 +38282,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[2] * B[3]\n\t"
- "ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[3] * B[2]\n\t"
"ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -38774,20 +38308,32 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #20]\n\t"
- "# A[0] * B[6]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[6] * B[0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
- "# A[1] * B[5]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #20]\n\t"
+ "# A[5] * B[1]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
+ "# A[4] * B[2]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[3]\n\t"
+ "ldr r11, [%[a], #12]\n\t"
+ "ldr r12, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[2] * B[4]\n\t"
"ldr r8, [%[a], #8]\n\t"
"ldr r9, [%[b], #16]\n\t"
@@ -38795,37 +38341,22 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[3] * B[3]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[1] * B[5]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[4] * B[2]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[1]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[0]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[0] * B[6]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #24]\n\t"
"# A[0] * B[7]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
@@ -38846,16 +38377,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[3] * B[4]\n\t"
- "ldr r8, [%[a], #12]\n\t"
"ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[4] * B[3]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #12]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -38881,44 +38410,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #28]\n\t"
- "# A[0] * B[8]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #32]\n\t"
+ "# A[8] * B[0]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
- "# A[1] * B[7]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[2] * B[6]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[3] * B[5]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[4] * B[4]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[3]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[7] * B[1]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -38930,23 +38430,49 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[7] * B[1]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[5] * B[3]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[4]\n\t"
+ "ldr r11, [%[a], #16]\n\t"
+ "ldr r12, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[5]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[8] * B[0]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[2] * B[6]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[1] * B[7]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #32]\n\t"
"# A[0] * B[9]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #36]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
@@ -38974,16 +38500,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[4] * B[5]\n\t"
- "ldr r8, [%[a], #16]\n\t"
"ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[5] * B[4]\n\t"
"ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -39016,58 +38540,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [sp, #36]\n\t"
- "# A[0] * B[10]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "ldr r9, [%[b], #40]\n\t"
+ "# A[10] * B[0]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
- "# A[1] * B[9]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[2] * B[8]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[3] * B[7]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[4] * B[6]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[5] * B[5]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[6] * B[4]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #16]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[7] * B[3]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[9] * B[1]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -39079,23 +38560,63 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[9] * B[1]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[7] * B[3]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[10] * B[0]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #0]\n\t"
+ "# A[6] * B[4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[5]\n\t"
+ "ldr r11, [%[a], #20]\n\t"
+ "ldr r12, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[6]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[7]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[8]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[9]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[0] * B[10]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [sp, #40]\n\t"
"# A[0] * B[11]\n\t"
- "ldr r8, [%[a], #0]\n\t"
"ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
@@ -39130,16 +38651,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[5] * B[6]\n\t"
- "ldr r8, [%[a], #20]\n\t"
"ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[6] * B[5]\n\t"
"ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -39179,58 +38698,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [sp, #44]\n\t"
- "# A[1] * B[11]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
- "# A[2] * B[10]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[3] * B[9]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[4] * B[8]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[5] * B[7]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[6] * B[6]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[7] * B[5]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[8] * B[4]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[10] * B[2]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -39242,16 +38718,57 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[10] * B[2]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #8]\n\t"
+ "# A[8] * B[4]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[11] * B[1]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #4]\n\t"
+ "# A[7] * B[5]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[6]\n\t"
+ "ldr r11, [%[a], #24]\n\t"
+ "ldr r12, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[7]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[8]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[9]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[10]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[1] * B[11]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -39259,7 +38776,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r3, [%[r], #48]\n\t"
"# A[2] * B[11]\n\t"
"ldr r8, [%[a], #8]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -39286,16 +38802,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[6] * B[7]\n\t"
- "ldr r8, [%[a], #24]\n\t"
"ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[7] * B[6]\n\t"
"ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -39328,44 +38842,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [%[r], #52]\n\t"
- "# A[3] * B[11]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r10, r10\n\t"
- "# A[4] * B[10]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[5] * B[9]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[6] * B[8]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[7] * B[7]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[8] * B[6]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #24]\n\t"
+ "# A[10] * B[4]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -39377,16 +38862,43 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[10] * B[4]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #16]\n\t"
+ "# A[8] * B[6]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[7]\n\t"
+ "ldr r11, [%[a], #28]\n\t"
+ "ldr r12, [%[b], #28]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[8]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
- "# A[11] * B[3]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #12]\n\t"
+ "# A[5] * B[9]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[10]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[11]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -39394,7 +38906,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r5, [%[r], #56]\n\t"
"# A[4] * B[11]\n\t"
"ldr r8, [%[a], #16]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -39414,16 +38925,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[7] * B[8]\n\t"
- "ldr r8, [%[a], #28]\n\t"
"ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"# A[8] * B[7]\n\t"
"ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
@@ -39449,20 +38958,32 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #60]\n\t"
- "# A[5] * B[11]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
- "# A[6] * B[10]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #40]\n\t"
+ "# A[10] * B[6]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
+ "# A[9] * B[7]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[8]\n\t"
+ "ldr r11, [%[a], #32]\n\t"
+ "ldr r12, [%[b], #32]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
"# A[7] * B[9]\n\t"
"ldr r8, [%[a], #28]\n\t"
"ldr r9, [%[b], #36]\n\t"
@@ -39470,30 +38991,16 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[8] * B[8]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #32]\n\t"
+ "# A[6] * B[10]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
- "# A[9] * B[7]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #28]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[10] * B[6]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
- "# A[11] * B[5]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #20]\n\t"
+ "# A[5] * B[11]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
@@ -39501,7 +39008,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r4, [%[r], #64]\n\t"
"# A[6] * B[11]\n\t"
"ldr r8, [%[a], #24]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
@@ -39514,16 +39020,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[8] * B[9]\n\t"
- "ldr r8, [%[a], #32]\n\t"
"ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"# A[9] * B[8]\n\t"
"ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
@@ -39542,13 +39046,25 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [%[r], #68]\n\t"
- "# A[7] * B[11]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "ldr r9, [%[b], #44]\n\t"
+ "# A[11] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
+ "# A[10] * B[8]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[9]\n\t"
+ "ldr r11, [%[a], #36]\n\t"
+ "ldr r12, [%[b], #36]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
"# A[8] * B[10]\n\t"
"ldr r8, [%[a], #32]\n\t"
"ldr r9, [%[b], #40]\n\t"
@@ -39556,23 +39072,9 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
- "# A[9] * B[9]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[10] * B[8]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #32]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
- "# A[11] * B[7]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #28]\n\t"
+ "# A[7] * B[11]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
@@ -39580,22 +39082,19 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"str r3, [%[r], #72]\n\t"
"# A[8] * B[11]\n\t"
"ldr r8, [%[a], #32]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r10, r10\n\t"
"# A[9] * B[10]\n\t"
- "ldr r8, [%[a], #36]\n\t"
"ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"# A[10] * B[9]\n\t"
"ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
@@ -39607,83 +39106,1397 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
"adcs r5, r5, r7\n\t"
"adc r3, r3, r10\n\t"
"str r4, [%[r], #76]\n\t"
+ "# A[11] * B[9]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[10] * B[10]\n\t"
+ "ldr r11, [%[a], #40]\n\t"
+ "ldr r12, [%[b], #40]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
"# A[9] * B[11]\n\t"
"ldr r8, [%[a], #36]\n\t"
"ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r10, r10\n\t"
- "# A[10] * B[10]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
- "# A[11] * B[9]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "umull r6, r7, r8, r9\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r7\n\t"
"adc r4, r4, r10\n\t"
"str r5, [%[r], #80]\n\t"
"# A[10] * B[11]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "ldr r9, [%[b], #44]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r11, r9\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r10, r10\n\t"
"# A[11] * B[10]\n\t"
"ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "umull r6, r7, r8, r9\n\t"
+ "umull r6, r7, r8, r12\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
"adc r5, r5, r10\n\t"
"str r3, [%[r], #84]\n\t"
"# A[11] * B[11]\n\t"
- "ldr r8, [%[a], #44]\n\t"
- "ldr r9, [%[b], #44]\n\t"
"umull r6, r7, r8, r9\n\t"
"adds r4, r4, r6\n\t"
"adc r5, r5, r7\n\t"
"str r4, [%[r], #88]\n\t"
"str r5, [%[r], #92]\n\t"
- "ldr r3, [sp, #0]\n\t"
- "ldr r4, [sp, #4]\n\t"
- "ldr r5, [sp, #8]\n\t"
- "ldr r6, [sp, #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [sp, #16]\n\t"
- "ldr r4, [sp, #20]\n\t"
- "ldr r5, [sp, #24]\n\t"
- "ldr r6, [sp, #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "ldr r3, [sp, #32]\n\t"
- "ldr r4, [sp, #36]\n\t"
- "ldr r5, [sp, #40]\n\t"
- "ldr r6, [sp, #44]\n\t"
- "str r3, [%[r], #32]\n\t"
- "str r4, [%[r], #36]\n\t"
- "str r5, [%[r], #40]\n\t"
- "str r6, [%[r], #44]\n\t"
- "add sp, sp, #48\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "sub %[r], %[r], #48\n\t"
:
: [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #96\n\t"
+ "mov r12, #0\n\t"
+ "mov r6, #0\n\t"
+ "mov r7, #0\n\t"
+ "mov r8, #0\n\t"
+ "mov r5, #0\n\t"
+ "\n1:\n\t"
+ "subs r3, r5, #44\n\t"
+ "it cc\n\t"
+ "movcc r3, r12\n\t"
+ "sub r4, r5, r3\n\t"
+ "\n2:\n\t"
+ "cmp r4, r3\n\t"
+ "beq 4f\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "ldr r9, [%[a], r4]\n\t"
+ "umull r9, r10, r14, r9\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "umull r9, r10, r14, r14\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "\n5:\n\t"
+ "add r3, r3, #4\n\t"
+ "sub r4, r4, #4\n\t"
+ "cmp r3, #48\n\t"
+ "beq 3f\n\t"
+ "cmp r3, r4\n\t"
+ "bgt 3f\n\t"
+ "cmp r3, r5\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "str r6, [sp, r5]\n\t"
+ "mov r6, r7\n\t"
+ "mov r7, r8\n\t"
+ "mov r8, #0\n\t"
+ "add r5, r5, #4\n\t"
+ "cmp r5, #88\n\t"
+ "ble 1b\n\t"
+ "str r6, [sp, r5]\n\t"
+ "\n4:\n\t"
+ "ldr r6, [sp, #0]\n\t"
+ "ldr r7, [sp, #4]\n\t"
+ "ldr r8, [sp, #8]\n\t"
+ "ldr r3, [sp, #12]\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "str r8, [%[r], #8]\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "add sp, sp, #16\n\t"
+ "add %[r], %[r], #16\n\t"
+ "subs r5, r5, #16\n\t"
+ "bgt 4b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
+ );
+}
+
+#else
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #48\n\t"
+ "mov r12, #0\n\t"
+ "# A[0] * A[0]\n\t"
+ "ldr r10, [%[a], #0]\n\t"
+ "umull r8, r3, r10, r10\n\t"
+ "mov r4, #0\n\t"
+ "str r8, [sp]\n\t"
+ "# A[0] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #4]\n\t"
+ "# A[0] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[1] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [sp, #8]\n\t"
+ "# A[0] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[1] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [sp, #12]\n\t"
+ "# A[0] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[1] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[2] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #16]\n\t"
+ "# A[0] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #20]\n\t"
+ "# A[0] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #24]\n\t"
+ "# A[0] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #28]\n\t"
+ "# A[0] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #32]\n\t"
+ "# A[0] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #36]\n\t"
+ "# A[0] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #40]\n\t"
+ "# A[0] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #44]\n\t"
+ "# A[1] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[2] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #48]\n\t"
+ "# A[2] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[3] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #52]\n\t"
+ "# A[3] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[4] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "# A[4] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[5] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #60]\n\t"
+ "# A[5] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[6] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "# A[6] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[7] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "# A[7] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[8] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[9] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [%[r], #72]\n\t"
+ "# A[8] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[9] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [%[r], #76]\n\t"
+ "# A[9] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[10] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "# A[10] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [%[r], #84]\n\t"
+ "# A[11] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adc r4, r4, r9\n\t"
+ "str r3, [%[r], #88]\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "sub %[r], %[r], #48\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12"
+ );
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #48\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], #-1\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "mov r4, #0\n\t"
+ "adc %[c], r4, #0\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "ldr r10, [%[b], #8]\n\t"
+ "ldr r14, [%[b], #12]\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "ldr r10, [%[b], #24]\n\t"
+ "ldr r14, [%[b], #28]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[a], #40]\n\t"
+ "ldr r7, [%[a], #44]\n\t"
+ "ldr r8, [%[b], #32]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "ldr r10, [%[b], #40]\n\t"
+ "ldr r14, [%[b], #44]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "adc %[c], r12, r12\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #48\n\t"
+ "\n1:\n\t"
+ "rsbs %[c], %[c], #0\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "sbc %[c], r4, r4\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r3, [%[a], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r7, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "ldr r10, [%[b], #12]\n\t"
+ "subs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #0]\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[a], #24]\n\t"
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r7, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "ldr r10, [%[b], #28]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "str r5, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ "ldr r3, [%[a], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[a], #40]\n\t"
+ "ldr r6, [%[a], #44]\n\t"
+ "ldr r7, [%[b], #32]\n\t"
+ "ldr r8, [%[b], #36]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "ldr r10, [%[b], #44]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #32]\n\t"
+ "str r4, [%[r], #36]\n\t"
+ "str r5, [%[r], #40]\n\t"
+ "str r6, [%[r], #44]\n\t"
+ "sbc %[c], %[c], #0\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp,
+ sp_point_384** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ int64_t* t;
+#else
+ int64_t t[12];
+#endif
+ int64_t o;
+ int err = MP_OKAY;
+
+ (void)m;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+
+ if (err == MP_OKAY) {
+ /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
+ t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11];
+ /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
+ t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11];
+ /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
+ t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11];
+ /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
+ t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11];
+ /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
+ t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11];
+ /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
+ t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11];
+ /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
+ t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11];
+ /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
+ t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11];
+ /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
+ t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8];
+ /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
+ t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9];
+ /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
+ t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10];
+ /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
+ t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11];
+
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+ o = t[11] >> 32; t[11] &= 0xffffffff;
+ t[0] += o;
+ t[1] -= o;
+ t[3] += o;
+ t[4] += o;
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+ r[3] = t[3];
+ r[4] = t[4];
+ r[5] = t[5];
+ r[6] = t[6];
+ r[7] = t[7];
+ r[8] = t[8];
+ r[9] = t[9];
+ r[10] = t[10];
+ r[11] = t[11];
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL)
+ XFREE(t, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+ return err;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_384.
+ *
+ * p Point of type sp_point_384 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_384_point_from_ecc_point_12(sp_point_384* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_384_from_mp(p->x, 12, pm->x);
+ sp_384_from_mp(p->y, 12, pm->y);
+ sp_384_from_mp(p->z, 12, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_384_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
+ r->used = 12;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_384 to type ecc_point.
+ *
+ * p Point of type sp_point_384.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_384_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -39804,6 +40617,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
sp_digit ca = 0;
__asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
"# i = 0\n\t"
"mov r12, #0\n\t"
"ldr r10, [%[a], #0]\n\t"
@@ -39812,13 +40626,12 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"# mu = a[i] * mp\n\t"
"mul r8, %[mp], r10\n\t"
"# a[i+0] += m[0] * mu\n\t"
- "ldr r7, [%[m], #0]\n\t"
"ldr r9, [%[a], #0]\n\t"
- "umull r6, r7, r8, r7\n\t"
+ "umull r6, r7, r8, r11\n\t"
"adds r10, r10, r6\n\t"
"adc r5, r7, #0\n\t"
"# a[i+1] += m[1] * mu\n\t"
- "ldr r7, [%[m], #4]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
"ldr r9, [%[a], #4]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r10, r14, r6\n\t"
@@ -39826,7 +40639,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"adds r10, r10, r5\n\t"
"adc r4, r4, #0\n\t"
"# a[i+2] += m[2] * mu\n\t"
- "ldr r7, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #8]\n\t"
"ldr r14, [%[a], #8]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r14, r14, r6\n\t"
@@ -39834,7 +40647,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"adds r14, r14, r4\n\t"
"adc r5, r5, #0\n\t"
"# a[i+3] += m[3] * mu\n\t"
- "ldr r7, [%[m], #12]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
"ldr r9, [%[a], #12]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39843,7 +40656,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #12]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+4] += m[4] * mu\n\t"
- "ldr r7, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #16]\n\t"
"ldr r9, [%[a], #16]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39852,7 +40665,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #16]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+5] += m[5] * mu\n\t"
- "ldr r7, [%[m], #20]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
"ldr r9, [%[a], #20]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39861,7 +40674,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #20]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+6] += m[6] * mu\n\t"
- "ldr r7, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #24]\n\t"
"ldr r9, [%[a], #24]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39870,7 +40683,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #24]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+7] += m[7] * mu\n\t"
- "ldr r7, [%[m], #28]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
"ldr r9, [%[a], #28]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39879,7 +40692,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #28]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+8] += m[8] * mu\n\t"
- "ldr r7, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #32]\n\t"
"ldr r9, [%[a], #32]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39888,7 +40701,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #32]\n\t"
"adc r5, r5, #0\n\t"
"# a[i+9] += m[9] * mu\n\t"
- "ldr r7, [%[m], #36]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
"ldr r9, [%[a], #36]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39897,7 +40710,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r9, [%[a], #36]\n\t"
"adc r4, r4, #0\n\t"
"# a[i+10] += m[10] * mu\n\t"
- "ldr r7, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #40]\n\t"
"ldr r9, [%[a], #40]\n\t"
"umull r6, r7, r8, r7\n\t"
"adds r9, r9, r6\n\t"
@@ -39928,7 +40741,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
"str r14, [%[a], #4]\n\t"
: [ca] "+r" (ca), [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
);
sp_384_cond_sub_12(a - 12, a, m, (sp_digit)0 - ca);
@@ -39943,788 +40756,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_384_mul_12(r, a, b);
sp_384_mont_reduce_12(r, m, mp);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #96\n\t"
- "mov r12, #0\n\t"
- "mov r6, #0\n\t"
- "mov r7, #0\n\t"
- "mov r8, #0\n\t"
- "mov r5, #0\n\t"
- "\n1:\n\t"
- "subs r3, r5, #44\n\t"
- "it cc\n\t"
- "movcc r3, r12\n\t"
- "sub r4, r5, r3\n\t"
- "\n2:\n\t"
- "cmp r4, r3\n\t"
- "beq 4f\n\t"
- "ldr r14, [%[a], r3]\n\t"
- "ldr r9, [%[a], r4]\n\t"
- "umull r9, r10, r14, r9\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "ldr r14, [%[a], r3]\n\t"
- "umull r9, r10, r14, r14\n\t"
- "adds r6, r6, r9\n\t"
- "adcs r7, r7, r10\n\t"
- "adc r8, r8, r12\n\t"
- "\n5:\n\t"
- "add r3, r3, #4\n\t"
- "sub r4, r4, #4\n\t"
- "cmp r3, #48\n\t"
- "beq 3f\n\t"
- "cmp r3, r4\n\t"
- "bgt 3f\n\t"
- "cmp r3, r5\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "str r6, [sp, r5]\n\t"
- "mov r6, r7\n\t"
- "mov r7, r8\n\t"
- "mov r8, #0\n\t"
- "add r5, r5, #4\n\t"
- "cmp r5, #88\n\t"
- "ble 1b\n\t"
- "str r6, [sp, r5]\n\t"
- "\n4:\n\t"
- "ldr r6, [sp, #0]\n\t"
- "ldr r7, [sp, #4]\n\t"
- "ldr r8, [sp, #8]\n\t"
- "ldr r3, [sp, #12]\n\t"
- "str r6, [%[r], #0]\n\t"
- "str r7, [%[r], #4]\n\t"
- "str r8, [%[r], #8]\n\t"
- "str r3, [%[r], #12]\n\t"
- "add sp, sp, #16\n\t"
- "add %[r], %[r], #16\n\t"
- "subs r5, r5, #16\n\t"
- "bgt 4b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
- );
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "sub sp, sp, #48\n\t"
- "mov r14, #0\n\t"
- "# A[0] * A[0]\n\t"
- "ldr r10, [%[a], #0]\n\t"
- "umull r8, r3, r10, r10\n\t"
- "mov r4, #0\n\t"
- "str r8, [sp]\n\t"
- "# A[0] * A[1]\n\t"
- "ldr r10, [%[a], #4]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [sp, #4]\n\t"
- "# A[0] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "# A[1] * A[1]\n\t"
- "ldr r10, [%[a], #4]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "str r4, [sp, #8]\n\t"
- "# A[0] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "# A[1] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "str r2, [sp, #12]\n\t"
- "# A[0] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[1] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[2] * A[2]\n\t"
- "ldr r10, [%[a], #8]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [sp, #16]\n\t"
- "# A[0] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [sp, #20]\n\t"
- "# A[0] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[3]\n\t"
- "ldr r10, [%[a], #12]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [sp, #24]\n\t"
- "# A[0] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r2, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r3, r3, r5\n\t"
- "adcs r4, r4, r6\n\t"
- "adc r2, r2, r7\n\t"
- "str r3, [sp, #28]\n\t"
- "# A[0] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[4]\n\t"
- "ldr r10, [%[a], #16]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [sp, #32]\n\t"
- "# A[0] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [sp, #36]\n\t"
- "# A[0] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r2, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[5] * A[5]\n\t"
- "ldr r10, [%[a], #20]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r3, r3, r5\n\t"
- "adcs r4, r4, r6\n\t"
- "adc r2, r2, r7\n\t"
- "str r3, [sp, #40]\n\t"
- "# A[0] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #0]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[1] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[2] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[5] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [sp, #44]\n\t"
- "# A[1] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #4]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[2] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[3] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[5] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[6] * A[6]\n\t"
- "ldr r10, [%[a], #24]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [%[r], #48]\n\t"
- "# A[2] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r2, #0\n\t"
- "mov r7, #0\n\t"
- "# A[3] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[4] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[5] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[6] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r3, r3, r5\n\t"
- "adcs r4, r4, r6\n\t"
- "adc r2, r2, r7\n\t"
- "str r3, [%[r], #52]\n\t"
- "# A[3] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[4] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[5] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[6] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[7] * A[7]\n\t"
- "ldr r10, [%[a], #28]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [%[r], #56]\n\t"
- "# A[4] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r4, #0\n\t"
- "mov r7, #0\n\t"
- "# A[5] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[6] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[7] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r2, r2, r5\n\t"
- "adcs r3, r3, r6\n\t"
- "adc r4, r4, r7\n\t"
- "str r2, [%[r], #60]\n\t"
- "# A[5] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r2, #0\n\t"
- "mov r7, #0\n\t"
- "# A[6] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[7] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[8] * A[8]\n\t"
- "ldr r10, [%[a], #32]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r3, r3, r5\n\t"
- "adcs r4, r4, r6\n\t"
- "adc r2, r2, r7\n\t"
- "str r3, [%[r], #64]\n\t"
- "# A[6] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r5, r6, r10, r8\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "# A[7] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "# A[8] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r5, r5, r8\n\t"
- "adcs r6, r6, r9\n\t"
- "adc r7, r7, r14\n\t"
- "adds r5, r5, r5\n\t"
- "adcs r6, r6, r6\n\t"
- "adc r7, r7, r7\n\t"
- "adds r4, r4, r5\n\t"
- "adcs r2, r2, r6\n\t"
- "adc r3, r3, r7\n\t"
- "str r4, [%[r], #68]\n\t"
- "# A[7] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "# A[8] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "# A[9] * A[9]\n\t"
- "ldr r10, [%[a], #36]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "str r2, [%[r], #72]\n\t"
- "# A[8] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #32]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r14, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "# A[9] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "adds r3, r3, r8\n\t"
- "adcs r4, r4, r9\n\t"
- "adc r2, r2, r14\n\t"
- "str r3, [%[r], #76]\n\t"
- "# A[9] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #36]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r14, r14\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "# A[10] * A[10]\n\t"
- "ldr r10, [%[a], #40]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r2, r2, r9\n\t"
- "adc r3, r3, r14\n\t"
- "str r4, [%[r], #80]\n\t"
- "# A[10] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "ldr r8, [%[a], #40]\n\t"
- "umull r8, r9, r10, r8\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r14, r14\n\t"
- "adds r2, r2, r8\n\t"
- "adcs r3, r3, r9\n\t"
- "adc r4, r4, r14\n\t"
- "str r2, [%[r], #84]\n\t"
- "# A[11] * A[11]\n\t"
- "ldr r10, [%[a], #44]\n\t"
- "umull r8, r9, r10, r10\n\t"
- "adds r3, r3, r8\n\t"
- "adc r4, r4, r9\n\t"
- "str r3, [%[r], #88]\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r2, [sp, #0]\n\t"
- "ldr r3, [sp, #4]\n\t"
- "ldr r4, [sp, #8]\n\t"
- "ldr r8, [sp, #12]\n\t"
- "str r2, [%[r], #0]\n\t"
- "str r3, [%[r], #4]\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r8, [%[r], #12]\n\t"
- "ldr r2, [sp, #16]\n\t"
- "ldr r3, [sp, #20]\n\t"
- "ldr r4, [sp, #24]\n\t"
- "ldr r8, [sp, #28]\n\t"
- "str r2, [%[r], #16]\n\t"
- "str r3, [%[r], #20]\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r8, [%[r], #28]\n\t"
- "ldr r2, [sp, #32]\n\t"
- "ldr r3, [sp, #36]\n\t"
- "ldr r4, [sp, #40]\n\t"
- "ldr r8, [sp, #44]\n\t"
- "str r2, [%[r], #32]\n\t"
- "str r3, [%[r], #36]\n\t"
- "str r4, [%[r], #40]\n\t"
- "str r8, [%[r], #44]\n\t"
- "add sp, sp, #48\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
- );
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -40732,8 +40770,8 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_384_sqr_12(r, a);
sp_384_mont_reduce_12(r, m, mp);
@@ -40757,7 +40795,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P384 curve. */
static const uint32_t p384_mod_minus_2[12] = {
@@ -41046,7 +41084,8 @@ static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
+static void sp_384_map_12(sp_point_384* r, const sp_point_384* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*12;
@@ -41082,122 +41121,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "add r12, %[a], #48\n\t"
- "\n1:\n\t"
- "adds %[c], %[c], #-1\n\t"
- "ldr r4, [%[a]], #4\n\t"
- "ldr r5, [%[a]], #4\n\t"
- "ldr r6, [%[a]], #4\n\t"
- "ldr r7, [%[a]], #4\n\t"
- "ldr r8, [%[b]], #4\n\t"
- "ldr r9, [%[b]], #4\n\t"
- "ldr r10, [%[b]], #4\n\t"
- "ldr r14, [%[b]], #4\n\t"
- "adcs r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r]], #4\n\t"
- "str r5, [%[r]], #4\n\t"
- "str r6, [%[r]], #4\n\t"
- "str r7, [%[r]], #4\n\t"
- "mov r4, #0\n\t"
- "adc %[c], r4, #0\n\t"
- "cmp %[a], r12\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r12, #0\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[a], #8]\n\t"
- "ldr r7, [%[a], #12]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "ldr r9, [%[b], #4]\n\t"
- "ldr r10, [%[b], #8]\n\t"
- "ldr r14, [%[b], #12]\n\t"
- "adds r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "str r6, [%[r], #8]\n\t"
- "str r7, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[a], #24]\n\t"
- "ldr r7, [%[a], #28]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "ldr r9, [%[b], #20]\n\t"
- "ldr r10, [%[b], #24]\n\t"
- "ldr r14, [%[b], #28]\n\t"
- "adcs r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "str r6, [%[r], #24]\n\t"
- "str r7, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[a], #36]\n\t"
- "ldr r6, [%[a], #40]\n\t"
- "ldr r7, [%[a], #44]\n\t"
- "ldr r8, [%[b], #32]\n\t"
- "ldr r9, [%[b], #36]\n\t"
- "ldr r10, [%[b], #40]\n\t"
- "ldr r14, [%[b], #44]\n\t"
- "adcs r4, r4, r8\n\t"
- "adcs r5, r5, r9\n\t"
- "adcs r6, r6, r10\n\t"
- "adcs r7, r7, r14\n\t"
- "str r4, [%[r], #32]\n\t"
- "str r5, [%[r], #36]\n\t"
- "str r6, [%[r], #40]\n\t"
- "str r7, [%[r], #44]\n\t"
- "adc %[c], r12, r12\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -41244,120 +41167,6 @@ static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m
sp_384_cond_sub_12(r, r, m, 0 - o);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "add r12, %[a], #48\n\t"
- "\n1:\n\t"
- "rsbs %[c], %[c], #0\n\t"
- "ldr r4, [%[a]], #4\n\t"
- "ldr r5, [%[a]], #4\n\t"
- "ldr r6, [%[a]], #4\n\t"
- "ldr r7, [%[a]], #4\n\t"
- "ldr r8, [%[b]], #4\n\t"
- "ldr r9, [%[b]], #4\n\t"
- "ldr r10, [%[b]], #4\n\t"
- "ldr r14, [%[b]], #4\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "sbcs r7, r7, r14\n\t"
- "str r4, [%[r]], #4\n\t"
- "str r5, [%[r]], #4\n\t"
- "str r6, [%[r]], #4\n\t"
- "str r7, [%[r]], #4\n\t"
- "sbc %[c], r4, r4\n\t"
- "cmp %[a], r12\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[a], #8]\n\t"
- "ldr r6, [%[a], #12]\n\t"
- "ldr r7, [%[b], #0]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "ldr r9, [%[b], #8]\n\t"
- "ldr r10, [%[b], #12]\n\t"
- "subs r3, r3, r7\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[a], #24]\n\t"
- "ldr r6, [%[a], #28]\n\t"
- "ldr r7, [%[b], #16]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "ldr r9, [%[b], #24]\n\t"
- "ldr r10, [%[b], #28]\n\t"
- "sbcs r3, r3, r7\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[a], #40]\n\t"
- "ldr r6, [%[a], #44]\n\t"
- "ldr r7, [%[b], #32]\n\t"
- "ldr r8, [%[b], #36]\n\t"
- "ldr r9, [%[b], #40]\n\t"
- "ldr r10, [%[b], #44]\n\t"
- "sbcs r3, r3, r7\n\t"
- "sbcs r4, r4, r8\n\t"
- "sbcs r5, r5, r9\n\t"
- "sbcs r6, r6, r10\n\t"
- "str r3, [%[r], #32]\n\t"
- "str r4, [%[r], #36]\n\t"
- "str r5, [%[r], #40]\n\t"
- "str r6, [%[r], #44]\n\t"
- "sbc %[c], %[c], #0\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -41970,8 +41779,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q,
- sp_digit* t)
+static void sp_384_proj_point_add_12(sp_point_384* r,
+ const sp_point_384* p, const sp_point_384* q, sp_digit* t)
{
const sp_point_384* ap[2];
sp_point_384* rp[2];
@@ -42150,9 +41959,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 384 doubles.
+ * 108 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -42181,7 +41992,8 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -42254,7 +42066,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
i = 10;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_384_get_point_16_12(rt, t, y);
@@ -42319,12 +42131,6 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_384 {
- sp_digit x[12];
- sp_digit y[12];
-} sp_table_entry_384;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -42333,7 +42139,8 @@ typedef struct sp_table_entry_384 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t)
+static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*12;
@@ -42414,6 +42221,36 @@ static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t)
sp_384_div2_12(y, y, p384_mod);
}
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 12;
+ sp_digit* tmp = t + 4 * 12;
+
+ sp_384_mont_inv_12(t1, a->z, tmp);
+
+ sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
+ sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
+
+ sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod);
+ sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod);
+ XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
+}
+
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_384 {
+ sp_digit x[12];
+ sp_digit y[12];
+} sp_table_entry_384;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -42499,29 +42336,11 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a Point to convert.
- * t Temporary data.
- */
-static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
-{
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2 * 12;
- sp_digit* tmp = t + 4 * 12;
-
- sp_384_mont_inv_12(t1, a->z, tmp);
-
- sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
- sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
-
- sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod);
- sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod);
- XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
-}
-
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 96 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -42532,12 +42351,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -42672,8 +42494,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -42695,8 +42519,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -42724,8 +42550,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=95; j<4; j++,x+=96) {
+ x = 95;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -42739,8 +42567,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=94; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=96) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -42782,16 +42612,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -42799,9 +42638,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -42910,6 +42755,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 48 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -42920,12 +42769,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -43060,8 +42912,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -43083,8 +42937,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -43112,8 +42968,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=47; j<8; j++,x+=48) {
+ x = 47;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -43127,8 +42985,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=46; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=48) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -43170,16 +43030,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -43187,9 +43056,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -43306,8 +43181,8 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -43348,7 +43223,94 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(point, gm);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 96 between points.
+ */
static const sp_table_entry_384 p384_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -43433,6 +43395,11 @@ static const sp_table_entry_384 p384_table[16] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -43448,6 +43415,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 48 between points.
+ */
static const sp_table_entry_384 p384_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -44732,6 +44703,11 @@ static const sp_table_entry_384 p384_table[256] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -44757,7 +44733,7 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -44798,6 +44774,87 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P384 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -44812,7 +44869,7 @@ static int sp_384_iszero_12(const sp_digit* a)
a[8] | a[9] | a[10] | a[11]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -44871,7 +44928,8 @@ static void sp_384_add_one_12(sp_digit* a)
*/
static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -45015,7 +45073,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_384_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 384 / 8 - 1;
a[j] = 0;
@@ -45056,7 +45117,7 @@ static void sp_384_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -45267,83 +45328,73 @@ static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a,
"str r3, [%[r]]\n\t"
"# A[1] * B\n\t"
"ldr r8, [%[a], #4]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #4]\n\t"
"# A[2] * B\n\t"
"ldr r8, [%[a], #8]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #8]\n\t"
"# A[3] * B\n\t"
"ldr r8, [%[a], #12]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #12]\n\t"
"# A[4] * B\n\t"
"ldr r8, [%[a], #16]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #16]\n\t"
"# A[5] * B\n\t"
"ldr r8, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #20]\n\t"
"# A[6] * B\n\t"
"ldr r8, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #24]\n\t"
"# A[7] * B\n\t"
"ldr r8, [%[a], #28]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #28]\n\t"
"# A[8] * B\n\t"
"ldr r8, [%[a], #32]\n\t"
- "mov r4, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r5, r5, r6\n\t"
"adcs r3, r3, r7\n\t"
- "adc r4, r4, r10\n\t"
+ "adc r4, r10, r10\n\t"
"str r5, [%[r], #32]\n\t"
"# A[9] * B\n\t"
"ldr r8, [%[a], #36]\n\t"
- "mov r5, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r3, r3, r6\n\t"
"adcs r4, r4, r7\n\t"
- "adc r5, r5, r10\n\t"
+ "adc r5, r10, r10\n\t"
"str r3, [%[r], #36]\n\t"
"# A[10] * B\n\t"
"ldr r8, [%[a], #40]\n\t"
- "mov r3, #0\n\t"
"umull r6, r7, %[b], r8\n\t"
"adds r4, r4, r6\n\t"
"adcs r5, r5, r7\n\t"
- "adc r3, r3, r10\n\t"
+ "adc r3, r10, r10\n\t"
"str r4, [%[r], #40]\n\t"
"# A[11] * B\n\t"
"ldr r8, [%[a], #44]\n\t"
@@ -45515,7 +45566,6 @@ static const uint32_t p384_order_minus_2[12] = {
/* The low half of the order-2 of the P384 curve. */
static const uint32_t p384_order_low[6] = {
0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
-
};
#endif /* WOLFSSL_SP_SMALL */
@@ -45663,7 +45713,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
sp_384_mont_mul_order_12(t2, t2, t);
for (i=191; i>=1; i--) {
sp_384_mont_sqr_order_12(t2, t2);
- if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_384_mont_mul_order_12(t2, t2, a);
}
}
@@ -45672,12 +45722,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_384_mul_12(k, k, p384_norm_order);
+ err = sp_384_mod_12(k, k, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(k);
+
+ /* kInv = 1/k mod order */
+ sp_384_mont_inv_order_12(kInv, k, tmp);
+ sp_384_norm_12(kInv);
+
+ /* s = r * x + e */
+ sp_384_mul_12(x, x, r);
+ err = sp_384_mod_12(x, x, p384_order);
+ }
+ if (err == MP_OKAY) {
+ sp_384_norm_12(x);
+ carry = sp_384_add_12(s, e, x);
+ sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
+ sp_384_norm_12(s);
+ c = sp_384_cmp_12(s, p384_order);
+ sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
+ sp_384_norm_12(s);
+
+ /* s = s * k^-1 mod order */
+ sp_384_mont_mul_order_12(s, s, kInv);
+ sp_384_norm_12(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 384 bits] from binary
* r = (k.G)->x mod order
@@ -45712,8 +45813,8 @@ typedef struct sp_ecc_sign_384_ctx {
int i;
} sp_ecc_sign_384_ctx;
-int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
@@ -45853,8 +45954,8 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -45872,11 +45973,9 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_384* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -45907,7 +46006,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 48U) {
hashLen = 48U;
@@ -45915,8 +46013,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_384_from_mp(x, 12, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_384_ecc_gen_k_12(rng, k);
@@ -45926,7 +46022,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL);
+ err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -45937,38 +46033,15 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0));
sp_384_norm_12(r);
- /* Conv k to Montgomery form (mod order) */
- sp_384_mul_12(k, k, p384_norm_order);
- err = sp_384_mod_12(k, k, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(k);
- /* kInv = 1/k mod order */
- sp_384_mont_inv_order_12(kInv, k, tmp);
- sp_384_norm_12(kInv);
-
- /* s = r * x + e */
- sp_384_mul_12(x, x, r);
- err = sp_384_mod_12(x, x, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(x);
+ sp_384_from_mp(x, 12, priv);
sp_384_from_bin(e, 12, hash, (int)hashLen);
- carry = sp_384_add_12(s, e, x);
- sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
- sp_384_norm_12(s);
- c = sp_384_cmp_12(s, p384_order);
- sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
- sp_384_norm_12(s);
- /* s = s * k^-1 mod order */
- sp_384_mont_mul_order_12(s, s, kInv);
- sp_384_norm_12(s);
+ err = sp_384_calc_s_12(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_384_iszero_12(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -45996,7 +46069,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U);
#endif
sp_384_point_free_12(point, 1, heap);
@@ -46335,6 +46407,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2,
+ sp_digit* tmp)
+{
+
+ sp_384_proj_point_add_12(p1, p1, p2, tmp);
+ if (sp_384_iszero_12(p1->z)) {
+ if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
+ sp_384_proj_point_dbl_12(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ p1->x[8] = 0;
+ p1->x[9] = 0;
+ p1->x[10] = 0;
+ p1->x[11] = 0;
+ XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_384_mod_inv_12(s, s, p384_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_384_mul_12(s, s, p384_norm_order);
+ }
+ err = sp_384_mod_12(s, s, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_384_mont_inv_order_12(s, s, tmp);
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#else
+ {
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_384_add_points_12(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 384)
@@ -46353,8 +46519,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_384_ctx {
@@ -46373,8 +46538,9 @@ typedef struct sp_ecc_verify_384_ctx {
sp_point_384 p2;
} sp_ecc_verify_384_ctx;
-int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
@@ -46528,8 +46694,9 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -46548,7 +46715,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_384* p1;
sp_point_384* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_384_point_new_12(heap, p1d, p1);
@@ -46589,70 +46756,9 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_384_from_mp(p2->y, 12, pY);
sp_384_from_mp(p2->z, 12, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_384_mod_inv_12(s, s, p384_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_384_mul_12(s, s, p384_norm_order);
- }
- err = sp_384_mod_12(s, s, p384_order);
+ err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_384_norm_12(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_384_mont_inv_order_12(s, s, tmp);
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#else
- {
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_384_proj_point_add_12(p1, p1, p2, tmp);
- if (sp_384_iszero_12(p1->z)) {
- if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
- sp_384_proj_point_dbl_12(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- p1->x[8] = 0;
- p1->x[9] = 0;
- p1->x[10] = 0;
- p1->x[11] = 0;
- XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_384_from_mp(u2, 12, r);
@@ -46674,16 +46780,16 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_384_cmp_12(u2, p384_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
- p384_mp_mod);
- *res = (int)(sp_384_cmp_12(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
+ p384_mp_mod);
+ *res = (sp_384_cmp_12(p1->x, u1) == 0);
}
}
}
@@ -46707,7 +46813,8 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
+static int sp_384_ecc_is_point_12(const sp_point_384* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -46770,7 +46877,7 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 pubd;
@@ -46804,7 +46911,8 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[12];
@@ -46858,12 +46966,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_384_cmp_12(pub->x, p384_mod) >= 0 ||
- sp_384_cmp_12(pub->y, p384_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(pub->x, p384_mod) >= 0) ||
+ (sp_384_cmp_12(pub->y, p384_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -46875,12 +46982,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_384_iszero_12(p->x) == 0) ||
- (sp_384_iszero_12(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) ||
+ (sp_384_iszero_12(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -46888,12 +46993,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_384_cmp_12(p->x, pub->x) != 0 ||
- sp_384_cmp_12(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(p->x, pub->x) != 0) ||
+ (sp_384_cmp_12(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -47083,7 +47187,7 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_384_from_mp(p->y, 12, pY);
sp_384_from_mp(p->z, 12, pZ);
- sp_384_map_12(p, p, tmp);
+ sp_384_map_12(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -47296,6 +47400,15869 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
}
#endif
#endif /* WOLFSSL_SP_384 */
+#ifdef WOLFSSL_SP_1024
+
+/* Point structure to use. */
+typedef struct sp_point_1024 {
+ /* X ordinate of point. */
+ sp_digit x[2 * 32];
+ /* Y ordinate of point. */
+ sp_digit y[2 * 32];
+ /* Z ordinate of point. */
+ sp_digit z[2 * 32];
+ /* Indicates point is at infinity. */
+ int infinity;
+} sp_point_1024;
+
+#ifndef WOLFSSL_SP_SMALL
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #64\n\t"
+ "mov r10, #0\n\t"
+ "# A[0] * B[0]\n\t"
+ "ldr r11, [%[a], #0]\n\t"
+ "ldr r12, [%[b], #0]\n\t"
+ "umull r3, r4, r11, r12\n\t"
+ "mov r5, #0\n\t"
+ "str r3, [sp]\n\t"
+ "# A[0] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[1] * B[0]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #4]\n\t"
+ "# A[2] * B[0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[1]\n\t"
+ "ldr r11, [%[a], #4]\n\t"
+ "ldr r12, [%[b], #4]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[2]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #8]\n\t"
+ "# A[0] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[1] * B[2]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[1]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[0]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #12]\n\t"
+ "# A[4] * B[0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[3] * B[1]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[2]\n\t"
+ "ldr r11, [%[a], #8]\n\t"
+ "ldr r12, [%[b], #8]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[3]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[0] * B[4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #16]\n\t"
+ "# A[0] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[4]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[2]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[1]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[0]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #20]\n\t"
+ "# A[6] * B[0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[5] * B[1]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[2]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[3]\n\t"
+ "ldr r11, [%[a], #12]\n\t"
+ "ldr r12, [%[b], #12]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[4]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[1] * B[5]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[0] * B[6]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #24]\n\t"
+ "# A[0] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[1] * B[6]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[5]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[4]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[3]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[2]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[1]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[0]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #28]\n\t"
+ "# A[8] * B[0]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[7] * B[1]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[2]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[3]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[4]\n\t"
+ "ldr r11, [%[a], #16]\n\t"
+ "ldr r12, [%[b], #16]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[5]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[6]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[1] * B[7]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #32]\n\t"
+ "# A[0] * B[9]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[1] * B[8]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[7]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[6]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[4]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[3]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[7] * B[2]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[8] * B[1]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[0]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #36]\n\t"
+ "# A[10] * B[0]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[9] * B[1]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[2]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[3]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[5]\n\t"
+ "ldr r11, [%[a], #20]\n\t"
+ "ldr r12, [%[b], #20]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[6]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[7]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[8]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[9]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[0] * B[10]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #40]\n\t"
+ "# A[0] * B[11]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[1] * B[10]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[9]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[8]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[7]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[6]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[5]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[4]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[8] * B[3]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[9] * B[2]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[10] * B[1]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[0]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #44]\n\t"
+ "# A[12] * B[0]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[11] * B[1]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[10] * B[2]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[3]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[8] * B[4]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[7] * B[5]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[6]\n\t"
+ "ldr r11, [%[a], #24]\n\t"
+ "ldr r12, [%[b], #24]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[7]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[8]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[9]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[10]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[1] * B[11]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[0] * B[12]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #48]\n\t"
+ "# A[0] * B[13]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[1] * B[12]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[11]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[10]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[9]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[8]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[6]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[5]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[9] * B[4]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[10] * B[3]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[11] * B[2]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[12] * B[1]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[0]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [sp, #52]\n\t"
+ "# A[14] * B[0]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[13] * B[1]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[12] * B[2]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[3]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[10] * B[4]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[9] * B[5]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[8] * B[6]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[7]\n\t"
+ "ldr r11, [%[a], #28]\n\t"
+ "ldr r12, [%[b], #28]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[8]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[9]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[10]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[3] * B[11]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[2] * B[12]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[1] * B[13]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[0] * B[14]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [sp, #56]\n\t"
+ "# A[0] * B[15]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[1] * B[14]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[2] * B[13]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[12]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[11]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[10]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[9]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[7] * B[8]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[8] * B[7]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[6]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[10] * B[5]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[11] * B[4]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[12] * B[3]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[13] * B[2]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[14] * B[1]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[15] * B[0]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #0]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [sp, #60]\n\t"
+ "# A[15] * B[1]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[14] * B[2]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[3]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[12] * B[4]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[11] * B[5]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[10] * B[6]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[9] * B[7]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[8]\n\t"
+ "ldr r11, [%[a], #32]\n\t"
+ "ldr r12, [%[b], #32]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[9]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[10]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[5] * B[11]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[4] * B[12]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[3] * B[13]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[2] * B[14]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[1] * B[15]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "# A[2] * B[15]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[3] * B[14]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[4] * B[13]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[12]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[11]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[10]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[8] * B[9]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[9] * B[8]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[10] * B[7]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[6]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[12] * B[5]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[13] * B[4]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[14] * B[3]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[15] * B[2]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "# A[15] * B[3]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[14] * B[4]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[13] * B[5]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[12] * B[6]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[11] * B[7]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[10] * B[8]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[9]\n\t"
+ "ldr r11, [%[a], #36]\n\t"
+ "ldr r12, [%[b], #36]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[8] * B[10]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[7] * B[11]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[6] * B[12]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[5] * B[13]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[4] * B[14]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[3] * B[15]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #72]\n\t"
+ "# A[4] * B[15]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[5] * B[14]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[6] * B[13]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[12]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[11]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[9] * B[10]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[10] * B[9]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[11] * B[8]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[12] * B[7]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[6]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[14] * B[5]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[15] * B[4]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #16]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #76]\n\t"
+ "# A[15] * B[5]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[14] * B[6]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[13] * B[7]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[12] * B[8]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[9]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[10] * B[10]\n\t"
+ "ldr r11, [%[a], #40]\n\t"
+ "ldr r12, [%[b], #40]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[9] * B[11]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[8] * B[12]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[7] * B[13]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[6] * B[14]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[5] * B[15]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #80]\n\t"
+ "# A[6] * B[15]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[7] * B[14]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[8] * B[13]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[12]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[10] * B[11]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[11] * B[10]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[12] * B[9]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[13] * B[8]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[14] * B[7]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[15] * B[6]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #84]\n\t"
+ "# A[15] * B[7]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[14] * B[8]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[9]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[12] * B[10]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[11] * B[11]\n\t"
+ "ldr r11, [%[a], #44]\n\t"
+ "ldr r12, [%[b], #44]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[10] * B[12]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[9] * B[13]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[8] * B[14]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[7] * B[15]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "# A[8] * B[15]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[9] * B[14]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[10] * B[13]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[12]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[12] * B[11]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[13] * B[10]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[14] * B[9]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[15] * B[8]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #32]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "# A[15] * B[9]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[14] * B[10]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[13] * B[11]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[12] * B[12]\n\t"
+ "ldr r11, [%[a], #48]\n\t"
+ "ldr r12, [%[b], #48]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[11] * B[13]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[10] * B[14]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[9] * B[15]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #96]\n\t"
+ "# A[10] * B[15]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[11] * B[14]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[12] * B[13]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[12]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[14] * B[11]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[15] * B[10]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #100]\n\t"
+ "# A[15] * B[11]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[14] * B[12]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[13] * B[13]\n\t"
+ "ldr r11, [%[a], #52]\n\t"
+ "ldr r12, [%[b], #52]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[12] * B[14]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "# A[11] * B[15]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #104]\n\t"
+ "# A[12] * B[15]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "# A[13] * B[14]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[14] * B[13]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "# A[15] * B[12]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "ldr r9, [%[b], #48]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], #108]\n\t"
+ "# A[15] * B[13]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "# A[14] * B[14]\n\t"
+ "ldr r11, [%[a], #56]\n\t"
+ "ldr r12, [%[b], #56]\n\t"
+ "umull r6, r7, r11, r12\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "# A[13] * B[15]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r3, r10\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "# A[14] * B[15]\n\t"
+ "umull r6, r7, r11, r9\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "# A[15] * B[14]\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "umull r6, r7, r8, r12\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r4, r10\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "# A[15] * B[15]\n\t"
+ "umull r6, r7, r8, r9\n\t"
+ "adds r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r3, [%[r], #120]\n\t"
+ "str r4, [%[r], #124]\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "ldm sp!, {r3, r4, r5, r6}\n\t"
+ "stm %[r]!, {r3, r4, r5, r6}\n\t"
+ "sub %[r], %[r], #64\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+ );
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #64\n\t"
+ "mov r12, #0\n\t"
+ "# A[0] * A[0]\n\t"
+ "ldr r10, [%[a], #0]\n\t"
+ "umull r8, r3, r10, r10\n\t"
+ "mov r4, #0\n\t"
+ "str r8, [sp]\n\t"
+ "# A[0] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #4]\n\t"
+ "# A[0] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[1] * A[1]\n\t"
+ "ldr r10, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [sp, #8]\n\t"
+ "# A[0] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[1] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [sp, #12]\n\t"
+ "# A[0] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[1] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[2] * A[2]\n\t"
+ "ldr r10, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [sp, #16]\n\t"
+ "# A[0] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #20]\n\t"
+ "# A[0] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[3]\n\t"
+ "ldr r10, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #24]\n\t"
+ "# A[0] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #28]\n\t"
+ "# A[0] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[4]\n\t"
+ "ldr r10, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #32]\n\t"
+ "# A[0] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #36]\n\t"
+ "# A[0] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[5]\n\t"
+ "ldr r10, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #40]\n\t"
+ "# A[0] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #44]\n\t"
+ "# A[0] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[6]\n\t"
+ "ldr r10, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #48]\n\t"
+ "# A[0] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [sp, #52]\n\t"
+ "# A[0] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[7]\n\t"
+ "ldr r10, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [sp, #56]\n\t"
+ "# A[0] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #0]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[1] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[2] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [sp, #60]\n\t"
+ "# A[1] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[2] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[3] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[8]\n\t"
+ "ldr r10, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "# A[2] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[3] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[4] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "# A[3] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[4] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[5] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[9] * A[9]\n\t"
+ "ldr r10, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #72]\n\t"
+ "# A[4] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[5] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[6] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[9] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #76]\n\t"
+ "# A[5] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[6] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[7] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[9] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[10] * A[10]\n\t"
+ "ldr r10, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "# A[6] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[7] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[8] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[9] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[10] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #84]\n\t"
+ "# A[7] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[8] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[9] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[10] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[11] * A[11]\n\t"
+ "ldr r10, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #88]\n\t"
+ "# A[8] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r3, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[9] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[10] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[11] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r2, r2, r6\n\t"
+ "adc r3, r3, r7\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "# A[9] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r4, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[10] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[11] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[12] * A[12]\n\t"
+ "ldr r10, [%[a], #48]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r2, r2, r5\n\t"
+ "adcs r3, r3, r6\n\t"
+ "adc r4, r4, r7\n\t"
+ "str r2, [%[r], #96]\n\t"
+ "# A[10] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r5, r6, r10, r8\n\t"
+ "mov r2, #0\n\t"
+ "mov r7, #0\n\t"
+ "# A[11] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "# A[12] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r5, r5, r8\n\t"
+ "adcs r6, r6, r9\n\t"
+ "adc r7, r7, r12\n\t"
+ "adds r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adc r7, r7, r7\n\t"
+ "adds r3, r3, r5\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adc r2, r2, r7\n\t"
+ "str r3, [%[r], #100]\n\t"
+ "# A[11] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[12] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "# A[13] * A[13]\n\t"
+ "ldr r10, [%[a], #52]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "# A[12] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r12, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "# A[13] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "adds r2, r2, r8\n\t"
+ "adcs r3, r3, r9\n\t"
+ "adc r4, r4, r12\n\t"
+ "str r2, [%[r], #108]\n\t"
+ "# A[13] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r12, r12\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "# A[14] * A[14]\n\t"
+ "ldr r10, [%[a], #56]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r3, r3, r8\n\t"
+ "adcs r4, r4, r9\n\t"
+ "adc r2, r2, r12\n\t"
+ "str r3, [%[r], #112]\n\t"
+ "# A[14] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "umull r8, r9, r10, r8\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r12, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r2, r2, r9\n\t"
+ "adc r3, r3, r12\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "# A[15] * A[15]\n\t"
+ "ldr r10, [%[a], #60]\n\t"
+ "umull r8, r9, r10, r10\n\t"
+ "adds r2, r2, r8\n\t"
+ "adc r3, r3, r9\n\t"
+ "str r2, [%[r], #120]\n\t"
+ "str r3, [%[r], #124]\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "ldm sp!, {r2, r3, r4, r8}\n\t"
+ "stm %[r]!, {r2, r3, r4, r8}\n\t"
+ "sub %[r], %[r], #64\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12"
+ );
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "ldr r10, [%[b], #8]\n\t"
+ "ldr r14, [%[b], #12]\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "ldr r10, [%[b], #24]\n\t"
+ "ldr r14, [%[b], #28]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[a], #40]\n\t"
+ "ldr r7, [%[a], #44]\n\t"
+ "ldr r8, [%[b], #32]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "ldr r10, [%[b], #40]\n\t"
+ "ldr r14, [%[b], #44]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[a], #56]\n\t"
+ "ldr r7, [%[a], #60]\n\t"
+ "ldr r8, [%[b], #48]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "ldr r10, [%[b], #56]\n\t"
+ "ldr r14, [%[b], #60]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "adc %[c], r12, r12\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer and result.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r2, [%[a], #0]\n\t"
+ "ldr r3, [%[a], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "ldr r9, [%[b], #12]\n\t"
+ "subs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #0]\n\t"
+ "str r3, [%[a], #4]\n\t"
+ "str r4, [%[a], #8]\n\t"
+ "str r5, [%[a], #12]\n\t"
+ "ldr r2, [%[a], #16]\n\t"
+ "ldr r3, [%[a], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "ldr r9, [%[b], #28]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #16]\n\t"
+ "str r3, [%[a], #20]\n\t"
+ "str r4, [%[a], #24]\n\t"
+ "str r5, [%[a], #28]\n\t"
+ "ldr r2, [%[a], #32]\n\t"
+ "ldr r3, [%[a], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "ldr r8, [%[b], #40]\n\t"
+ "ldr r9, [%[b], #44]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #32]\n\t"
+ "str r3, [%[a], #36]\n\t"
+ "str r4, [%[a], #40]\n\t"
+ "str r5, [%[a], #44]\n\t"
+ "ldr r2, [%[a], #48]\n\t"
+ "ldr r3, [%[a], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "ldr r8, [%[b], #56]\n\t"
+ "ldr r9, [%[b], #60]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #48]\n\t"
+ "str r3, [%[a], #52]\n\t"
+ "str r4, [%[a], #56]\n\t"
+ "str r5, [%[a], #60]\n\t"
+ "ldr r2, [%[a], #64]\n\t"
+ "ldr r3, [%[a], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "ldr r8, [%[b], #72]\n\t"
+ "ldr r9, [%[b], #76]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #64]\n\t"
+ "str r3, [%[a], #68]\n\t"
+ "str r4, [%[a], #72]\n\t"
+ "str r5, [%[a], #76]\n\t"
+ "ldr r2, [%[a], #80]\n\t"
+ "ldr r3, [%[a], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "ldr r8, [%[b], #88]\n\t"
+ "ldr r9, [%[b], #92]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #80]\n\t"
+ "str r3, [%[a], #84]\n\t"
+ "str r4, [%[a], #88]\n\t"
+ "str r5, [%[a], #92]\n\t"
+ "ldr r2, [%[a], #96]\n\t"
+ "ldr r3, [%[a], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "ldr r8, [%[b], #104]\n\t"
+ "ldr r9, [%[b], #108]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #96]\n\t"
+ "str r3, [%[a], #100]\n\t"
+ "str r4, [%[a], #104]\n\t"
+ "str r5, [%[a], #108]\n\t"
+ "ldr r2, [%[a], #112]\n\t"
+ "ldr r3, [%[a], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "ldr r8, [%[b], #120]\n\t"
+ "ldr r9, [%[b], #124]\n\t"
+ "sbcs r2, r2, r6\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "str r2, [%[a], #112]\n\t"
+ "str r3, [%[a], #116]\n\t"
+ "str r4, [%[a], #120]\n\t"
+ "str r5, [%[a], #124]\n\t"
+ "sbc %[c], r9, r9\n\t"
+ : [c] "+r" (c)
+ : [a] "r" (a), [b] "r" (b)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
+ );
+
+ return c;
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "ldr r9, [%[b], #4]\n\t"
+ "ldr r10, [%[b], #8]\n\t"
+ "ldr r14, [%[b], #12]\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "ldr r9, [%[b], #20]\n\t"
+ "ldr r10, [%[b], #24]\n\t"
+ "ldr r14, [%[b], #28]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[a], #40]\n\t"
+ "ldr r7, [%[a], #44]\n\t"
+ "ldr r8, [%[b], #32]\n\t"
+ "ldr r9, [%[b], #36]\n\t"
+ "ldr r10, [%[b], #40]\n\t"
+ "ldr r14, [%[b], #44]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[a], #56]\n\t"
+ "ldr r7, [%[a], #60]\n\t"
+ "ldr r8, [%[b], #48]\n\t"
+ "ldr r9, [%[b], #52]\n\t"
+ "ldr r10, [%[b], #56]\n\t"
+ "ldr r14, [%[b], #60]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[a], #72]\n\t"
+ "ldr r7, [%[a], #76]\n\t"
+ "ldr r8, [%[b], #64]\n\t"
+ "ldr r9, [%[b], #68]\n\t"
+ "ldr r10, [%[b], #72]\n\t"
+ "ldr r14, [%[b], #76]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "str r6, [%[r], #72]\n\t"
+ "str r7, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[a], #88]\n\t"
+ "ldr r7, [%[a], #92]\n\t"
+ "ldr r8, [%[b], #80]\n\t"
+ "ldr r9, [%[b], #84]\n\t"
+ "ldr r10, [%[b], #88]\n\t"
+ "ldr r14, [%[b], #92]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "str r6, [%[r], #88]\n\t"
+ "str r7, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[a], #104]\n\t"
+ "ldr r7, [%[a], #108]\n\t"
+ "ldr r8, [%[b], #96]\n\t"
+ "ldr r9, [%[b], #100]\n\t"
+ "ldr r10, [%[b], #104]\n\t"
+ "ldr r14, [%[b], #108]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "str r6, [%[r], #104]\n\t"
+ "str r7, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[a], #120]\n\t"
+ "ldr r7, [%[a], #124]\n\t"
+ "ldr r8, [%[b], #112]\n\t"
+ "ldr r9, [%[b], #116]\n\t"
+ "ldr r10, [%[b], #120]\n\t"
+ "ldr r14, [%[b], #124]\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "str r6, [%[r], #120]\n\t"
+ "str r7, [%[r], #124]\n\t"
+ "adc %[c], r12, r12\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<16; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 16; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit* z0 = r;
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit b1[16];
+ sp_digit z2[32];
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
+
+ ca = sp_1024_add_16(a1, a, &a[16]);
+ cb = sp_1024_add_16(b1, b, &b[16]);
+ u = ca & cb;
+ sp_1024_mul_16(z1, a1, b1);
+ sp_1024_mul_16(z2, &a[16], &b[16]);
+ sp_1024_mul_16(z0, a, b);
+ sp_1024_mask_16(r + 32, a1, 0 - cb);
+ sp_1024_mask_16(b1, b1, 0 - ca);
+ u += sp_1024_add_16(r + 32, r + 32, b1);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ sp_digit* z0 = r;
+ sp_digit z2[32];
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit u;
+
+ u = sp_1024_add_16(a1, a, &a[16]);
+ sp_1024_sqr_16(z1, a1);
+ sp_1024_sqr_16(z2, &a[16]);
+ sp_1024_sqr_16(z0, a);
+ sp_1024_mask_16(r + 32, a1, 0 - u);
+ u += sp_1024_add_16(r + 32, r + 32, r + 32);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+#else
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #256\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #0\n\t"
+ "mov r7, #0\n\t"
+ "mov r8, #0\n\t"
+ "\n1:\n\t"
+ "subs r3, r5, #124\n\t"
+ "it cc\n\t"
+ "movcc r3, #0\n\t"
+ "sub r4, r5, r3\n\t"
+ "\n2:\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "ldr r12, [%[b], r4]\n\t"
+ "umull r9, r10, r14, r12\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, #0\n\t"
+ "add r3, r3, #4\n\t"
+ "sub r4, r4, #4\n\t"
+ "cmp r3, #128\n\t"
+ "beq 3f\n\t"
+ "cmp r3, r5\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "str r6, [sp, r5]\n\t"
+ "mov r6, r7\n\t"
+ "mov r7, r8\n\t"
+ "mov r8, #0\n\t"
+ "add r5, r5, #4\n\t"
+ "cmp r5, #248\n\t"
+ "ble 1b\n\t"
+ "str r6, [sp, r5]\n\t"
+ "\n4:\n\t"
+ "ldr r6, [sp, #0]\n\t"
+ "ldr r7, [sp, #4]\n\t"
+ "ldr r8, [sp, #8]\n\t"
+ "ldr r3, [sp, #12]\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "str r8, [%[r], #8]\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "add sp, sp, #16\n\t"
+ "add %[r], %[r], #16\n\t"
+ "subs r5, r5, #16\n\t"
+ "bgt 4b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "sub sp, sp, #256\n\t"
+ "mov r12, #0\n\t"
+ "mov r6, #0\n\t"
+ "mov r7, #0\n\t"
+ "mov r8, #0\n\t"
+ "mov r5, #0\n\t"
+ "\n1:\n\t"
+ "subs r3, r5, #124\n\t"
+ "it cc\n\t"
+ "movcc r3, r12\n\t"
+ "sub r4, r5, r3\n\t"
+ "\n2:\n\t"
+ "cmp r4, r3\n\t"
+ "beq 4f\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "ldr r9, [%[a], r4]\n\t"
+ "umull r9, r10, r14, r9\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "ldr r14, [%[a], r3]\n\t"
+ "umull r9, r10, r14, r14\n\t"
+ "adds r6, r6, r9\n\t"
+ "adcs r7, r7, r10\n\t"
+ "adc r8, r8, r12\n\t"
+ "\n5:\n\t"
+ "add r3, r3, #4\n\t"
+ "sub r4, r4, #4\n\t"
+ "cmp r3, #128\n\t"
+ "beq 3f\n\t"
+ "cmp r3, r4\n\t"
+ "bgt 3f\n\t"
+ "cmp r3, r5\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "str r6, [sp, r5]\n\t"
+ "mov r6, r7\n\t"
+ "mov r7, r8\n\t"
+ "mov r8, #0\n\t"
+ "add r5, r5, #4\n\t"
+ "cmp r5, #248\n\t"
+ "ble 1b\n\t"
+ "str r6, [sp, r5]\n\t"
+ "\n4:\n\t"
+ "ldr r6, [sp, #0]\n\t"
+ "ldr r7, [sp, #4]\n\t"
+ "ldr r8, [sp, #8]\n\t"
+ "ldr r3, [sp, #12]\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "str r8, [%[r], #8]\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "add sp, sp, #16\n\t"
+ "add %[r], %[r], #16\n\t"
+ "subs r5, r5, #16\n\t"
+ "bgt 4b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
+ );
+}
+
+#endif /* !WOLFSSL_SP_SMALL */
+/* The modulus (prime) of the curve P1024. */
+static const sp_digit p1024_mod[32] = {
+ 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823,
+ 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8,
+ 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4,
+ 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27,
+ 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198,
+ 0x0a563fda,0x997abb1f
+};
+/* The Montogmery normalizer for modulus of the curve P1024. */
+static const sp_digit p1024_norm_mod[32] = {
+ 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc,
+ 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57,
+ 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b,
+ 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8,
+ 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67,
+ 0xf5a9c025,0x668544e0
+};
+/* The Montogmery multiplier for modulus of the curve P1024. */
+static sp_digit p1024_mp_mod = 0x7c8f2f3d;
+#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
+/* The order of the curve P1024. */
+static const sp_digit p1024_order[32] = {
+ 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08,
+ 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a,
+ 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd,
+ 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9,
+ 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466,
+ 0xc2958ff6,0x265eaec7
+};
+#endif
+/* The base point of curve P1024. */
+static const sp_point_1024 p1024_base = {
+ /* X ordinate */
+ {
+ 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5,
+ 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339,
+ 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7,
+ 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0,
+ 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005,
+ 0x332c29ad,0x53fc09ee,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Y ordinate */
+ {
+ 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a,
+ 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80,
+ 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c,
+ 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4,
+ 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053,
+ 0x3f6009f1,0x0a824906,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Z ordinate */
+ {
+ 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* infinity */
+ 0
+};
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r14, #0\n\t"
+ "add r12, %[a], #128\n\t"
+ "\n1:\n\t"
+ "subs %[c], r14, %[c]\n\t"
+ "ldr r3, [%[a]]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r7, [%[b]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[a]], #4\n\t"
+ "str r4, [%[a]], #4\n\t"
+ "str r5, [%[a]], #4\n\t"
+ "str r6, [%[a]], #4\n\t"
+ "sbc %[c], r14, r14\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ sp_digit m)
+{
+ sp_digit c = 0;
+
+#ifdef WOLFSSL_SP_SMALL
+ __asm__ __volatile__ (
+ "mov r9, #0\n\t"
+ "mov r8, #0\n\t"
+ "1:\n\t"
+ "subs %[c], r9, %[c]\n\t"
+ "ldr r4, [%[a], r8]\n\t"
+ "ldr r5, [%[b], r8]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbc %[c], r9, r9\n\t"
+ "str r4, [%[r], r8]\n\t"
+ "add r8, r8, #4\n\t"
+ "cmp r8, #128\n\t"
+ "blt 1b\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
+ );
+#else
+ __asm__ __volatile__ (
+
+ "mov r9, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "subs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r6, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r6, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r6, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r6, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r6, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r6, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r6, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r6, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r6, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "ldr r7, [%[b], #60]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r6, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r6, [%[a], #68]\n\t"
+ "ldr r5, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r6, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r6, [%[a], #76]\n\t"
+ "ldr r5, [%[b], #72]\n\t"
+ "ldr r7, [%[b], #76]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r6, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r6, [%[a], #84]\n\t"
+ "ldr r5, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r6, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r6, [%[a], #92]\n\t"
+ "ldr r5, [%[b], #88]\n\t"
+ "ldr r7, [%[b], #92]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r6, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r6, [%[a], #100]\n\t"
+ "ldr r5, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r6, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r6, [%[a], #108]\n\t"
+ "ldr r5, [%[b], #104]\n\t"
+ "ldr r7, [%[b], #108]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r6, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r6, [%[a], #116]\n\t"
+ "ldr r5, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r6, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r6, [%[a], #124]\n\t"
+ "ldr r5, [%[b], #120]\n\t"
+ "ldr r7, [%[b], #124]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "sbcs r6, r6, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r6, [%[r], #124]\n\t"
+ "sbc %[c], r9, r9\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
+ );
+#endif /* WOLFSSL_SP_SMALL */
+
+ return c;
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #128\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], #-1\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "mov r4, #0\n\t"
+ "adc %[c], r4, #0\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Mul a by digit b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision digit.
+ */
+static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a,
+ sp_digit b)
+{
+#ifdef WOLFSSL_SP_SMALL
+ __asm__ __volatile__ (
+ "mov r10, #0\n\t"
+ "# A[0] * B\n\t"
+ "ldr r8, [%[a]]\n\t"
+ "umull r5, r3, %[b], r8\n\t"
+ "mov r4, #0\n\t"
+ "str r5, [%[r]]\n\t"
+ "mov r5, #0\n\t"
+ "mov r9, #4\n\t"
+ "1:\n\t"
+ "ldr r8, [%[a], r9]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r5, r10\n\t"
+ "str r3, [%[r], r9]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r9, r9, #4\n\t"
+ "cmp r9, #128\n\t"
+ "blt 1b\n\t"
+ "str r3, [%[r], #128]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ );
+#else
+ __asm__ __volatile__ (
+ "mov r10, #0\n\t"
+ "# A[0] * B\n\t"
+ "ldr r8, [%[a]]\n\t"
+ "umull r3, r4, %[b], r8\n\t"
+ "mov r5, #0\n\t"
+ "str r3, [%[r]]\n\t"
+ "# A[1] * B\n\t"
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "# A[2] * B\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "# A[3] * B\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #12]\n\t"
+ "# A[4] * B\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "# A[5] * B\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "# A[6] * B\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #24]\n\t"
+ "# A[7] * B\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #28]\n\t"
+ "# A[8] * B\n\t"
+ "ldr r8, [%[a], #32]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #32]\n\t"
+ "# A[9] * B\n\t"
+ "ldr r8, [%[a], #36]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #36]\n\t"
+ "# A[10] * B\n\t"
+ "ldr r8, [%[a], #40]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "# A[11] * B\n\t"
+ "ldr r8, [%[a], #44]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "# A[12] * B\n\t"
+ "ldr r8, [%[a], #48]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #48]\n\t"
+ "# A[13] * B\n\t"
+ "ldr r8, [%[a], #52]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "# A[14] * B\n\t"
+ "ldr r8, [%[a], #56]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #56]\n\t"
+ "# A[15] * B\n\t"
+ "ldr r8, [%[a], #60]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #60]\n\t"
+ "# A[16] * B\n\t"
+ "ldr r8, [%[a], #64]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "# A[17] * B\n\t"
+ "ldr r8, [%[a], #68]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "# A[18] * B\n\t"
+ "ldr r8, [%[a], #72]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #72]\n\t"
+ "# A[19] * B\n\t"
+ "ldr r8, [%[a], #76]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #76]\n\t"
+ "# A[20] * B\n\t"
+ "ldr r8, [%[a], #80]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #80]\n\t"
+ "# A[21] * B\n\t"
+ "ldr r8, [%[a], #84]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #84]\n\t"
+ "# A[22] * B\n\t"
+ "ldr r8, [%[a], #88]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "# A[23] * B\n\t"
+ "ldr r8, [%[a], #92]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "# A[24] * B\n\t"
+ "ldr r8, [%[a], #96]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #96]\n\t"
+ "# A[25] * B\n\t"
+ "ldr r8, [%[a], #100]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #100]\n\t"
+ "# A[26] * B\n\t"
+ "ldr r8, [%[a], #104]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #104]\n\t"
+ "# A[27] * B\n\t"
+ "ldr r8, [%[a], #108]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #108]\n\t"
+ "# A[28] * B\n\t"
+ "ldr r8, [%[a], #112]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r7\n\t"
+ "adc r3, r10, r10\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "# A[29] * B\n\t"
+ "ldr r8, [%[a], #116]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r7\n\t"
+ "adc r4, r10, r10\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "# A[30] * B\n\t"
+ "ldr r8, [%[a], #120]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r7\n\t"
+ "adc r5, r10, r10\n\t"
+ "str r3, [%[r], #120]\n\t"
+ "# A[31] * B\n\t"
+ "ldr r8, [%[a], #124]\n\t"
+ "umull r6, r7, %[b], r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adc r5, r5, r7\n\t"
+ "str r4, [%[r], #124]\n\t"
+ "str r5, [%[r], #128]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ );
+#endif
+}
+
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ *
+ * Note that this is an approximate div. It may give an answer 1 larger.
+ */
+static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit div)
+{
+ sp_digit r = 0;
+
+ __asm__ __volatile__ (
+ "lsr r5, %[div], #1\n\t"
+ "add r5, r5, #1\n\t"
+ "mov r6, %[d0]\n\t"
+ "mov r7, %[d1]\n\t"
+ "# Do top 32\n\t"
+ "subs r8, r5, r7\n\t"
+ "sbc r8, r8, r8\n\t"
+ "add %[r], %[r], %[r]\n\t"
+ "sub %[r], %[r], r8\n\t"
+ "and r8, r8, r5\n\t"
+ "subs r7, r7, r8\n\t"
+ "# Next 30 bits\n\t"
+ "mov r4, #29\n\t"
+ "1:\n\t"
+ "movs r6, r6, lsl #1\n\t"
+ "adc r7, r7, r7\n\t"
+ "subs r8, r5, r7\n\t"
+ "sbc r8, r8, r8\n\t"
+ "add %[r], %[r], %[r]\n\t"
+ "sub %[r], %[r], r8\n\t"
+ "and r8, r8, r5\n\t"
+ "subs r7, r7, r8\n\t"
+ "subs r4, r4, #1\n\t"
+ "bpl 1b\n\t"
+ "add %[r], %[r], %[r]\n\t"
+ "add %[r], %[r], #1\n\t"
+ "umull r4, r5, %[r], %[div]\n\t"
+ "subs r4, %[d0], r4\n\t"
+ "sbc r5, %[d1], r5\n\t"
+ "add %[r], %[r], r5\n\t"
+ "umull r4, r5, %[r], %[div]\n\t"
+ "subs r4, %[d0], r4\n\t"
+ "sbc r5, %[d1], r5\n\t"
+ "add %[r], %[r], r5\n\t"
+ "umull r4, r5, %[r], %[div]\n\t"
+ "subs r4, %[d0], r4\n\t"
+ "sbc r5, %[d1], r5\n\t"
+ "add %[r], %[r], r5\n\t"
+ "subs r8, %[div], r4\n\t"
+ "sbc r8, r8, r8\n\t"
+ "sub %[r], %[r], r8\n\t"
+ : [r] "+r" (r)
+ : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
+ : "r4", "r5", "r6", "r7", "r8"
+ );
+ return r;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<32; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Compare a with b in constant time.
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ * return -ve, 0 or +ve if a is less than, equal to or greater than b
+ * respectively.
+ */
+static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b)
+{
+ sp_digit r = -1;
+ sp_digit one = 1;
+
+
+#ifdef WOLFSSL_SP_SMALL
+ __asm__ __volatile__ (
+ "mov r7, #0\n\t"
+ "mov r3, #-1\n\t"
+ "mov r6, #124\n\t"
+ "1:\n\t"
+ "ldr r4, [%[a], r6]\n\t"
+ "ldr r5, [%[b], r6]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "subs r6, r6, #4\n\t"
+ "bcs 1b\n\t"
+ "eor %[r], %[r], r3\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b), [one] "r" (one)
+ : "r3", "r4", "r5", "r6", "r7"
+ );
+#else
+ __asm__ __volatile__ (
+ "mov r7, #0\n\t"
+ "mov r3, #-1\n\t"
+ "ldr r4, [%[a], #124]\n\t"
+ "ldr r5, [%[b], #124]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[b], #120]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "ldr r5, [%[b], #116]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[b], #112]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #108]\n\t"
+ "ldr r5, [%[b], #108]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[b], #104]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #100]\n\t"
+ "ldr r5, [%[b], #100]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[b], #96]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "ldr r5, [%[b], #92]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[b], #88]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #84]\n\t"
+ "ldr r5, [%[b], #84]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[b], #80]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #76]\n\t"
+ "ldr r5, [%[b], #76]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[b], #72]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "ldr r5, [%[b], #68]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[b], #64]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #60]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #52]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #44]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #36]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #28]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #20]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #12]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #4]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "and r4, r4, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "subs r4, r4, r5\n\t"
+ "it hi\n\t"
+ "movhi %[r], %[one]\n\t"
+ "it lo\n\t"
+ "movlo %[r], r3\n\t"
+ "it ne\n\t"
+ "movne r3, r7\n\t"
+ "eor %[r], %[r], r3\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b), [one] "r" (one)
+ : "r3", "r4", "r5", "r6", "r7"
+ );
+#endif
+
+ return r;
+}
+
+/* Divide d in a and put remainder into r (m*d + r = a)
+ * m is not calculated as it is not needed at this time.
+ *
+ * a Number to be divided.
+ * d Number to divide with.
+ * m Multiplier result.
+ * r Remainder from the division.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m,
+ sp_digit* r)
+{
+ sp_digit t1[64], t2[33];
+ sp_digit div, r1;
+ int i;
+
+ (void)m;
+
+
+ div = d[31];
+ XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
+ for (i=31; i>=0; i--) {
+ sp_digit hi = t1[32 + i] - (t1[32 + i] == div);
+ r1 = div_1024_word_32(hi, t1[32 + i - 1], div);
+
+ sp_1024_mul_d_32(t2, d, r1);
+ t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2);
+ t1[32 + i] -= t2[32];
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ }
+
+ r1 = sp_1024_cmp_32(t1, d) >= 0;
+ sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
+
+ return MP_OKAY;
+}
+
+/* Reduce a modulo m into r. (r = a mod m)
+ *
+ * r A single precision number that is the reduced result.
+ * a A single precision number that is to be reduced.
+ * m A single precision number that is the modulus to reduce with.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ return sp_1024_div_32(a, m, NULL, r);
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
+{
+ sp_1024_mul_32(r, a, p1024_norm_mod);
+ return sp_1024_mod_32(r, r, m);
+}
+
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp,
+ sp_point_1024** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_1024.
+ *
+ * p Point of type sp_point_1024 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_1024_point_from_ecc_point_32(sp_point_1024* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_1024_from_mp(p->x, 32, pm->x);
+ sp_1024_from_mp(p->y, 32, pm->y);
+ sp_1024_from_mp(p->z, 32, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
+ r->used = 32;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_1024 to type ecc_point.
+ *
+ * p Point of type sp_point_1024.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_1024_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
+/* Reduce the number back to 1024 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m,
+ sp_digit mp)
+{
+ sp_digit ca = 0;
+
+ __asm__ __volatile__ (
+ "ldr r11, [%[m], #0]\n\t"
+ "# i = 0\n\t"
+ "mov r12, #0\n\t"
+ "ldr r10, [%[a], #0]\n\t"
+ "ldr r14, [%[a], #4]\n\t"
+ "\n1:\n\t"
+ "# mu = a[i] * mp\n\t"
+ "mul r8, %[mp], r10\n\t"
+ "# a[i+0] += m[0] * mu\n\t"
+ "ldr r9, [%[a], #0]\n\t"
+ "umull r6, r7, r8, r11\n\t"
+ "adds r10, r10, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "# a[i+1] += m[1] * mu\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "ldr r9, [%[a], #4]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r10, r14, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r10, r10, r5\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+2] += m[2] * mu\n\t"
+ "ldr r7, [%[m], #8]\n\t"
+ "ldr r14, [%[a], #8]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r14, r14, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r14, r14, r4\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+3] += m[3] * mu\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "ldr r9, [%[a], #12]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #12]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+4] += m[4] * mu\n\t"
+ "ldr r7, [%[m], #16]\n\t"
+ "ldr r9, [%[a], #16]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #16]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+5] += m[5] * mu\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "ldr r9, [%[a], #20]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #20]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+6] += m[6] * mu\n\t"
+ "ldr r7, [%[m], #24]\n\t"
+ "ldr r9, [%[a], #24]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #24]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+7] += m[7] * mu\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "ldr r9, [%[a], #28]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #28]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+8] += m[8] * mu\n\t"
+ "ldr r7, [%[m], #32]\n\t"
+ "ldr r9, [%[a], #32]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #32]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+9] += m[9] * mu\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "ldr r9, [%[a], #36]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #36]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+10] += m[10] * mu\n\t"
+ "ldr r7, [%[m], #40]\n\t"
+ "ldr r9, [%[a], #40]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #40]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+11] += m[11] * mu\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "ldr r9, [%[a], #44]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #44]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+12] += m[12] * mu\n\t"
+ "ldr r7, [%[m], #48]\n\t"
+ "ldr r9, [%[a], #48]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #48]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+13] += m[13] * mu\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "ldr r9, [%[a], #52]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #52]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+14] += m[14] * mu\n\t"
+ "ldr r7, [%[m], #56]\n\t"
+ "ldr r9, [%[a], #56]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #56]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+15] += m[15] * mu\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "ldr r9, [%[a], #60]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #60]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+16] += m[16] * mu\n\t"
+ "ldr r7, [%[m], #64]\n\t"
+ "ldr r9, [%[a], #64]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #64]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+17] += m[17] * mu\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "ldr r9, [%[a], #68]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #68]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+18] += m[18] * mu\n\t"
+ "ldr r7, [%[m], #72]\n\t"
+ "ldr r9, [%[a], #72]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #72]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+19] += m[19] * mu\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "ldr r9, [%[a], #76]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #76]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+20] += m[20] * mu\n\t"
+ "ldr r7, [%[m], #80]\n\t"
+ "ldr r9, [%[a], #80]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #80]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+21] += m[21] * mu\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "ldr r9, [%[a], #84]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #84]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+22] += m[22] * mu\n\t"
+ "ldr r7, [%[m], #88]\n\t"
+ "ldr r9, [%[a], #88]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #88]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+23] += m[23] * mu\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "ldr r9, [%[a], #92]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #92]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+24] += m[24] * mu\n\t"
+ "ldr r7, [%[m], #96]\n\t"
+ "ldr r9, [%[a], #96]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #96]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+25] += m[25] * mu\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "ldr r9, [%[a], #100]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #100]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+26] += m[26] * mu\n\t"
+ "ldr r7, [%[m], #104]\n\t"
+ "ldr r9, [%[a], #104]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #104]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+27] += m[27] * mu\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "ldr r9, [%[a], #108]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #108]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+28] += m[28] * mu\n\t"
+ "ldr r7, [%[m], #112]\n\t"
+ "ldr r9, [%[a], #112]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #112]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+29] += m[29] * mu\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "ldr r9, [%[a], #116]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r4, r7, #0\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #116]\n\t"
+ "adc r4, r4, #0\n\t"
+ "# a[i+30] += m[30] * mu\n\t"
+ "ldr r7, [%[m], #120]\n\t"
+ "ldr r9, [%[a], #120]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r9, r9, r6\n\t"
+ "adc r5, r7, #0\n\t"
+ "adds r9, r9, r4\n\t"
+ "str r9, [%[a], #120]\n\t"
+ "adc r5, r5, #0\n\t"
+ "# a[i+31] += m[31] * mu\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "ldr r9, [%[a], #124]\n\t"
+ "umull r6, r7, r8, r7\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r7, r7, %[ca]\n\t"
+ "mov %[ca], #0\n\t"
+ "adc %[ca], %[ca], %[ca]\n\t"
+ "adds r9, r9, r5\n\t"
+ "str r9, [%[a], #124]\n\t"
+ "ldr r9, [%[a], #128]\n\t"
+ "adcs r9, r9, r7\n\t"
+ "str r9, [%[a], #128]\n\t"
+ "adc %[ca], %[ca], #0\n\t"
+ "# i += 1\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add r12, r12, #4\n\t"
+ "cmp r12, #128\n\t"
+ "blt 1b\n\t"
+ "str r10, [%[a], #0]\n\t"
+ "str r14, [%[a], #4]\n\t"
+ "ldr r6, [%[m], #124]\n\t"
+ "subs r9, r6, r9\n\t"
+ "neg %[ca], %[ca]\n\t"
+ "sbc r9, r9, r9\n\t"
+ "orr %[ca], %[ca], r9\n\t"
+ : [ca] "+r" (ca), [a] "+r" (a)
+ : [m] "r" (m), [mp] "r" (mp)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11"
+ );
+
+ sp_1024_cond_sub_32(a - 32, a, m, ca);
+}
+
+/* Multiply two Montogmery form numbers mod the modulus (prime).
+ * (r = a * b mod m)
+ *
+ * r Result of multiplication.
+ * a First number to multiply in Montogmery form.
+ * b Second number to multiply in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
+{
+ sp_1024_mul_32(r, a, b);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Square the Montgomery form number. (r = a * a mod m)
+ *
+ * r Result of squaring.
+ * a Number to square in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
+{
+ sp_1024_sqr_32(r, a);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Mod-2 for the P1024 curve. */
+static const uint8_t p1024_mod_minus_2[] = {
+ 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
+ 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
+ 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
+ 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
+ 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
+ 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
+ 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
+ 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
+ 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
+ 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
+ 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
+ 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
+ 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
+ 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
+ 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
+ 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
+ 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
+ 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
+ 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
+};
+
+/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
+ * P1024 curve. (r = 1 / a mod m)
+ *
+ * r Inverse result.
+ * a Number to invert.
+ * td Temporary data.
+ */
+static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a,
+ sp_digit* td)
+{
+ sp_digit* t = td;
+ int i;
+ int j;
+ sp_digit table[32][2 * 32];
+
+ XMEMCPY(table[0], a, sizeof(sp_digit) * 32);
+ for (i = 1; i < 6; i++) {
+ sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod);
+ }
+ for (i = 1; i < 32; i++) {
+ sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
+ }
+
+ XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32);
+ for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
+ for (j = 0; j < p1024_mod_minus_2[i]; j++) {
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ }
+ sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
+ p1024_mp_mod);
+ }
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod);
+}
+
+/* Normalize the values in each word to 32.
+ *
+ * a Array of sp_digit to normalize.
+ */
+#define sp_1024_norm_32(a)
+
+/* Map the Montgomery form projective coordinate point to an affine point.
+ *
+ * r Resulting affine coordinate point.
+ * p Montgomery form projective coordinate point.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p,
+ sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ int32_t n;
+
+ sp_1024_mont_inv_32(t1, p->z, t + 2*32);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ /* x /= z^2 */
+ sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U);
+ sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod);
+ /* Reduce x to less than modulus */
+ n = sp_1024_cmp_32(r->x, p1024_mod);
+ sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->x);
+
+ /* y /= z^3 */
+ sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U);
+ sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod);
+ /* Reduce y to less than modulus */
+ n = sp_1024_cmp_32(r->y, p1024_mod);
+ sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->y);
+
+ XMEMSET(r->z, 0, sizeof(r->z));
+ r->z[0] = 1;
+
+}
+
+/* Add two Montgomery form numbers (r = a + b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldr r14, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r14, r14, r7\n\t"
+ "neg r12, r12\n\t"
+ "sbc r14, r14, r14\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r14\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Double a Montgomery form number (r = a + a % m).
+ *
+ * r Result of doubling.
+ * a Number to double in Montogmery form.
+ * m Modulus (prime).
+ */
+static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r4, r4, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r4, r4, r4\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r4\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Triple a Montgomery form number (r = a + a + a % m).
+ *
+ * r Result of Tripling.
+ * a Number to triple in Montogmery form.
+ * m Modulus (prime).
+ */
+static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r4, r4, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r4, r4, r4\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r4\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "sub %[m], %[m], #128\n\t"
+ "sub %[a], %[a], #128\n\t"
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adds r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r7, r7, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r7, r7, r7\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r7\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "subs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbc r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Subtract two Montgomery form numbers (r = a - b % m).
+ *
+ * r Result of subtration.
+ * a Number to subtract from in Montogmery form.
+ * b Number to subtract with in Montogmery form.
+ * m Modulus (prime).
+ */
+static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sbc r12, r12, r12\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Conditionally add a and b using the mask m.
+ * m is -1 to add and 0 when not.
+ *
+ * r A single precision number representing conditional add result.
+ * a A single precision number to add with.
+ * b A single precision number to add.
+ * m Mask value to apply.
+ */
+static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ sp_digit m)
+{
+ sp_digit c = 0;
+
+#ifdef WOLFSSL_SP_SMALL
+ __asm__ __volatile__ (
+ "mov r9, #0\n\t"
+ "mov r8, #0\n\t"
+ "1:\n\t"
+ "adds %[c], %[c], #-1\n\t"
+ "ldr r4, [%[a], r8]\n\t"
+ "ldr r5, [%[b], r8]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adc %[c], r9, r9\n\t"
+ "str r4, [%[r], r8]\n\t"
+ "add r8, r8, #4\n\t"
+ "cmp r8, #128\n\t"
+ "blt 1b\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
+ );
+#else
+ __asm__ __volatile__ (
+
+ "mov r9, #0\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adds r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r6, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r6, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r6, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r6, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r6, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r6, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r6, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r6, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r6, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "ldr r7, [%[b], #60]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r6, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r6, [%[a], #68]\n\t"
+ "ldr r5, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r6, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r6, [%[a], #76]\n\t"
+ "ldr r5, [%[b], #72]\n\t"
+ "ldr r7, [%[b], #76]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r6, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r6, [%[a], #84]\n\t"
+ "ldr r5, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r6, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r6, [%[a], #92]\n\t"
+ "ldr r5, [%[b], #88]\n\t"
+ "ldr r7, [%[b], #92]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r6, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r6, [%[a], #100]\n\t"
+ "ldr r5, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r6, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r6, [%[a], #108]\n\t"
+ "ldr r5, [%[b], #104]\n\t"
+ "ldr r7, [%[b], #108]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r6, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r6, [%[a], #116]\n\t"
+ "ldr r5, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r6, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r6, [%[a], #124]\n\t"
+ "ldr r5, [%[b], #120]\n\t"
+ "ldr r7, [%[b], #124]\n\t"
+ "and r5, r5, %[m]\n\t"
+ "and r7, r7, %[m]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "adcs r6, r6, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r6, [%[r], #124]\n\t"
+ "adc %[c], r9, r9\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
+ );
+#endif /* WOLFSSL_SP_SMALL */
+
+ return c;
+}
+
+static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "ldr r2, [%[a]]\n\t"
+ "ldr r3, [%[a], #4]\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "str r2, [%[r], #0]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #12]\n\t"
+ "str r3, [%[r], #4]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "str r2, [%[r], #12]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #24]\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #28]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "str r2, [%[r], #24]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #36]\n\t"
+ "str r3, [%[r], #28]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #40]\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "str r2, [%[r], #36]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #48]\n\t"
+ "str r3, [%[r], #40]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #52]\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "str r2, [%[r], #48]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #60]\n\t"
+ "str r3, [%[r], #52]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #64]\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "str r2, [%[r], #60]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #72]\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #76]\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "str r2, [%[r], #72]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #84]\n\t"
+ "str r3, [%[r], #76]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #88]\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "str r2, [%[r], #84]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #96]\n\t"
+ "str r3, [%[r], #88]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #100]\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "str r2, [%[r], #96]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #108]\n\t"
+ "str r3, [%[r], #100]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #112]\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "str r2, [%[r], #108]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #120]\n\t"
+ "str r3, [%[r], #112]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #124]\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "str r2, [%[r], #120]\n\t"
+ "str r3, [%[r], #124]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4"
+ );
+}
+
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ sp_digit o;
+
+ o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1));
+ sp_1024_rshift1_32(r, r);
+ r[31] |= o << 31;
+}
+
+/* Double the Montgomery form projective point p.
+ *
+ * r Result of doubling point.
+ * p Point to double.
+ * t Temporary ordinate data.
+ */
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_dbl_32_ctx {
+ int state;
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_dbl_32_ctx;
+
+static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data;
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0:
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->x = r->x;
+ ctx->y = r->y;
+ ctx->z = r->z;
+
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+ ctx->state = 1;
+ break;
+ case 1:
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 2;
+ break;
+ case 2:
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 3;
+ break;
+ case 3:
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod);
+ ctx->state = 4;
+ break;
+ case 4:
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* T2 = T2/2 */
+ sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod);
+ ctx->state = 19;
+ /* fall-through */
+ case 19:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 19) {
+ err = FP_WOULDBLOCK;
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = r->x;
+ y = r->y;
+ z = r->z;
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(z, z, p1024_mod);
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod);
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod);
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(t1, t2, p1024_mod);
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(y, p->y, p1024_mod);
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod);
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod);
+ /* T2 = T2/2 */
+ sp_1024_div2_32(t2, t2, p1024_mod);
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod);
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod);
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(y, y, t2, p1024_mod);
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "add r12, %[a], #128\n\t"
+ "\n1:\n\t"
+ "rsbs %[c], %[c], #0\n\t"
+ "ldr r4, [%[a]], #4\n\t"
+ "ldr r5, [%[a]], #4\n\t"
+ "ldr r6, [%[a]], #4\n\t"
+ "ldr r7, [%[a]], #4\n\t"
+ "ldr r8, [%[b]], #4\n\t"
+ "ldr r9, [%[b]], #4\n\t"
+ "ldr r10, [%[b]], #4\n\t"
+ "ldr r14, [%[b]], #4\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "str r4, [%[r]], #4\n\t"
+ "str r5, [%[r]], #4\n\t"
+ "str r6, [%[r]], #4\n\t"
+ "str r7, [%[r]], #4\n\t"
+ "sbc %[c], r4, r4\n\t"
+ "cmp %[a], r12\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r3, [%[a], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[a], #8]\n\t"
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r7, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "ldr r9, [%[b], #8]\n\t"
+ "ldr r10, [%[b], #12]\n\t"
+ "subs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #0]\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[a], #24]\n\t"
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r7, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "ldr r9, [%[b], #24]\n\t"
+ "ldr r10, [%[b], #28]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "str r5, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ "ldr r3, [%[a], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[a], #40]\n\t"
+ "ldr r6, [%[a], #44]\n\t"
+ "ldr r7, [%[b], #32]\n\t"
+ "ldr r8, [%[b], #36]\n\t"
+ "ldr r9, [%[b], #40]\n\t"
+ "ldr r10, [%[b], #44]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #32]\n\t"
+ "str r4, [%[r], #36]\n\t"
+ "str r5, [%[r], #40]\n\t"
+ "str r6, [%[r], #44]\n\t"
+ "ldr r3, [%[a], #48]\n\t"
+ "ldr r4, [%[a], #52]\n\t"
+ "ldr r5, [%[a], #56]\n\t"
+ "ldr r6, [%[a], #60]\n\t"
+ "ldr r7, [%[b], #48]\n\t"
+ "ldr r8, [%[b], #52]\n\t"
+ "ldr r9, [%[b], #56]\n\t"
+ "ldr r10, [%[b], #60]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #48]\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "str r5, [%[r], #56]\n\t"
+ "str r6, [%[r], #60]\n\t"
+ "ldr r3, [%[a], #64]\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "ldr r5, [%[a], #72]\n\t"
+ "ldr r6, [%[a], #76]\n\t"
+ "ldr r7, [%[b], #64]\n\t"
+ "ldr r8, [%[b], #68]\n\t"
+ "ldr r9, [%[b], #72]\n\t"
+ "ldr r10, [%[b], #76]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "str r5, [%[r], #72]\n\t"
+ "str r6, [%[r], #76]\n\t"
+ "ldr r3, [%[a], #80]\n\t"
+ "ldr r4, [%[a], #84]\n\t"
+ "ldr r5, [%[a], #88]\n\t"
+ "ldr r6, [%[a], #92]\n\t"
+ "ldr r7, [%[b], #80]\n\t"
+ "ldr r8, [%[b], #84]\n\t"
+ "ldr r9, [%[b], #88]\n\t"
+ "ldr r10, [%[b], #92]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #80]\n\t"
+ "str r4, [%[r], #84]\n\t"
+ "str r5, [%[r], #88]\n\t"
+ "str r6, [%[r], #92]\n\t"
+ "ldr r3, [%[a], #96]\n\t"
+ "ldr r4, [%[a], #100]\n\t"
+ "ldr r5, [%[a], #104]\n\t"
+ "ldr r6, [%[a], #108]\n\t"
+ "ldr r7, [%[b], #96]\n\t"
+ "ldr r8, [%[b], #100]\n\t"
+ "ldr r9, [%[b], #104]\n\t"
+ "ldr r10, [%[b], #108]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #96]\n\t"
+ "str r4, [%[r], #100]\n\t"
+ "str r5, [%[r], #104]\n\t"
+ "str r6, [%[r], #108]\n\t"
+ "ldr r3, [%[a], #112]\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "ldr r5, [%[a], #120]\n\t"
+ "ldr r6, [%[a], #124]\n\t"
+ "ldr r7, [%[b], #112]\n\t"
+ "ldr r8, [%[b], #116]\n\t"
+ "ldr r9, [%[b], #120]\n\t"
+ "ldr r10, [%[b], #124]\n\t"
+ "sbcs r3, r3, r7\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "str r3, [%[r], #112]\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "str r5, [%[r], #120]\n\t"
+ "str r6, [%[r], #124]\n\t"
+ "sbc %[c], %[c], #0\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Compare two numbers to determine if they are equal.
+ * Constant time implementation.
+ *
+ * a First number to compare.
+ * b Second number to compare.
+ * returns 1 when equal and 0 otherwise.
+ */
+static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b)
+{
+ return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
+ (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) |
+ (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
+ (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) |
+ (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) |
+ (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
+ (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) |
+ (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0;
+}
+
+/* Add two Montgomery form projective points.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_add_32_ctx {
+ int state;
+ sp_1024_proj_point_dbl_32_ctx dbl_ctx;
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* t3;
+ sp_digit* t4;
+ sp_digit* t5;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_add_32_ctx;
+
+static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0: /* INIT */
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->t3 = t + 4*32;
+ ctx->t4 = t + 6*32;
+ ctx->t5 = t + 8*32;
+
+ ctx->state = 1;
+ break;
+ case 1:
+ /* Check double */
+ (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y);
+ sp_1024_norm_32(ctx->t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0)
+ {
+ XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
+ ctx->state = 2;
+ }
+ else {
+ ctx->state = 3;
+ }
+ break;
+ case 2:
+ err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
+ if (err == MP_OKAY)
+ ctx->state = 27; /* done */
+ break;
+ case 3:
+ {
+ int i;
+ ctx->rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024));
+ ctx->x = ctx->rp[p->infinity | q->infinity]->x;
+ ctx->y = ctx->rp[p->infinity | q->infinity]->y;
+ ctx->z = ctx->rp[p->infinity | q->infinity]->z;
+
+ ctx->ap[0] = p;
+ ctx->ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ctx->ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ctx->ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ctx->ap[p->infinity]->z[i];
+ }
+ r->infinity = ctx->ap[p->infinity]->infinity;
+
+ ctx->state = 4;
+ break;
+ }
+ case 4:
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
+ ctx->state = 19;
+ break;
+ case 19:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 20;
+ break;
+ case 20:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod);
+ ctx->state = 21;
+ break;
+ case 21:
+ sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod);
+ ctx->state = 22;
+ break;
+ case 22:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod);
+ ctx->state = 23;
+ break;
+ case 23:
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 24;
+ break;
+ case 24:
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 25;
+ break;
+ case 25:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
+ ctx->state = 26;
+ break;
+ case 26:
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod);
+ ctx->state = 27;
+ /* fall-through */
+ case 27:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 27) {
+ err = FP_WOULDBLOCK;
+ }
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_add_32(sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod);
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(t4, t4, t3, p1024_mod);
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, x, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, y, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, y, t5, p1024_mod);
+ }
+}
+
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 1024 doubles.
+ * 268 adds.
+ *
+ * r Resulting point.
+ * g Point to multiply.
+ * k Scalar to multiply by.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
+ int map, int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td[16];
+ sp_point_1024 rtd;
+ sp_digit tmpd[2 * 32 * 5];
+#endif
+ sp_point_1024* t;
+ sp_point_1024* rt;
+ sp_digit* tmp;
+ sp_digit n;
+ int i;
+ int c;
+ int y;
+ int err;
+
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+#ifndef WC_NO_CACHE_RESISTANT
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 17, heap, DYNAMIC_TYPE_ECC);
+#else
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 16, heap, DYNAMIC_TYPE_ECC);
+#endif
+ if (t == NULL)
+ err = MEMORY_E;
+ tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (tmp == NULL)
+ err = MEMORY_E;
+#else
+ t = td;
+ tmp = tmpd;
+#endif
+
+ if (err == MP_OKAY) {
+ /* t[0] = {0, 0, 1} * norm */
+ XMEMSET(&t[0], 0, sizeof(t[0]));
+ t[0].infinity = 1;
+ /* t[1] = {g->x, g->y, g->z} * norm */
+ (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod);
+ t[1].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp);
+ t[ 2].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp);
+ t[ 3].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp);
+ t[ 4].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp);
+ t[ 5].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp);
+ t[ 6].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp);
+ t[ 7].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp);
+ t[ 8].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp);
+ t[ 9].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp);
+ t[10].infinity = 0;
+ sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp);
+ t[11].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp);
+ t[12].infinity = 0;
+ sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp);
+ t[13].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp);
+ t[14].infinity = 0;
+ sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp);
+ t[15].infinity = 0;
+
+ i = 30;
+ n = k[i+1] << 0;
+ c = 28;
+ y = (int)(n >> 28);
+ XMEMCPY(rt, &t[y], sizeof(sp_point_1024));
+ n <<= 4;
+ for (; i>=0 || c>=4; ) {
+ if (c < 4) {
+ n |= k[i--];
+ c += 32;
+ }
+ y = (n >> 28) & 0xf;
+ n <<= 4;
+ c -= 4;
+
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_add_32(rt, rt, &t[y], tmp);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, tmp);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (tmp != NULL) {
+ XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 32 * 5);
+ XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
+ }
+ if (t != NULL) {
+ XMEMSET(t, 0, sizeof(sp_point_1024) * 16);
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+ ForceZero(tmpd, sizeof(tmpd));
+ ForceZero(td, sizeof(td));
+#endif
+ sp_1024_point_free_32(rt, 1, heap);
+
+ return err;
+}
+
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Double the Montgomery form projective point p a number of times.
+ *
+ * r Result of repeated doubling of point.
+ * p Point to double.
+ * n Number of times to double
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n,
+ sp_digit* t)
+{
+ sp_digit* w = t;
+ sp_digit* a = t + 2*32;
+ sp_digit* b = t + 4*32;
+ sp_digit* t1 = t + 6*32;
+ sp_digit* t2 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = p->x;
+ y = p->y;
+ z = p->z;
+
+ /* Y = 2*Y */
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ /* W = Z^4 */
+ sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod);
+
+#ifndef WOLFSSL_SP_SMALL
+ while (--n > 0)
+#else
+ while (--n >= 0)
+#endif
+ {
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+#ifdef WOLFSSL_SP_SMALL
+ if (n != 0)
+#endif
+ {
+ /* W = W*Y^4 */
+ sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod);
+ }
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+ }
+#ifndef WOLFSSL_SP_SMALL
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+#endif
+ /* Y = Y/2 */
+ sp_1024_div2_32(y, y, p1024_mod);
+}
+
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* tmp = t + 4 * 32;
+
+ sp_1024_mont_inv_32(t1, a->z, tmp);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_1024 {
+ sp_digit x[32];
+ sp_digit y[32];
+} sp_table_entry_1024;
+
+#ifdef FP_ECC
+#endif /* FP_ECC */
+/* Add two Montgomery form projective points. The second point has a q value of
+ * one.
+ * Only the first point can be the same pointer as the result point.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p,
+ const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - X1 */
+ sp_1024_mont_sub_32(t2, t2, x, p1024_mod);
+ /* R = S2 - Y1 */
+ sp_1024_mont_sub_32(t4, t4, y, p1024_mod);
+ /* Z3 = H*Z1 */
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*X1*H^2 */
+ sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, t1, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, t3, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
+ sp_1024_mont_sub_32(t3, t3, x, p1024_mod);
+ sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, t3, t5, p1024_mod);
+ }
+}
+
+#ifdef WOLFSSL_SP_SMALL
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 256 bits between
+ *
+ * a The base point.
+ * table Place to store generated point data.
+ * tmp Temporary data.
+ * heap Heap to use for allocation.
+ */
+static int sp_1024_gen_stripe_table_32(const sp_point_1024* a,
+ sp_table_entry_1024* table, sp_digit* tmp, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td;
+ sp_point_1024 s1d;
+ sp_point_1024 s2d;
+#endif
+ sp_point_1024* t;
+ sp_point_1024* s1 = NULL;
+ sp_point_1024* s2 = NULL;
+ int i;
+ int j;
+ int err;
+
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, td, t);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s1d, s1);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s2d, s2);
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ t->infinity = 0;
+ sp_1024_proj_to_affine_32(t, tmp);
+
+ XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s1->infinity = 0;
+ XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s2->infinity = 0;
+
+ /* table[0] = {0, 0, infinity} */
+ XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
+ /* table[1] = Affine version of 'a' in Montgomery form */
+ XMEMCPY(table[1].x, t->x, sizeof(table->x));
+ XMEMCPY(table[1].y, t->y, sizeof(table->y));
+
+ for (i=1; i<4; i++) {
+ sp_1024_proj_point_dbl_n_32(t, 256, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[1<x, sizeof(table->x));
+ XMEMCPY(table[1<y, sizeof(table->y));
+ }
+
+ for (i=1; i<4; i++) {
+ XMEMCPY(s1->x, table[1<x));
+ XMEMCPY(s1->y, table[1<y));
+ for (j=(1<x, table[j-(1<x));
+ XMEMCPY(s2->y, table[j-(1<y));
+ sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[j].x, t->x, sizeof(table->x));
+ XMEMCPY(table[j].y, t->y, sizeof(table->y));
+ }
+ }
+ }
+
+ sp_1024_point_free_32(s2, 0, heap);
+ sp_1024_point_free_32(s1, 0, heap);
+ sp_1024_point_free_32( t, 0, heap);
+
+ return err;
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^256, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
+ * r Resulting point.
+ * k Scalar to multiply by.
+ * table Pre-computed table.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g,
+ const sp_table_entry_1024* table, const sp_digit* k, int map,
+ int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 rtd;
+ sp_point_1024 pd;
+ sp_digit td[2 * 32 * 5];
+#endif
+ sp_point_1024* rt;
+ sp_point_1024* p = NULL;
+ sp_digit* t;
+ int i;
+ int j;
+ int y;
+ int x;
+ int err;
+
+ (void)g;
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#else
+ t = td;
+#endif
+
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+
+ y = 0;
+ x = 255;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+ XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
+ rt->infinity = !y;
+ for (i=254; i>=0; i--) {
+ y = 0;
+ x = i;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+
+ sp_1024_proj_point_dbl_32(rt, rt, t);
+ XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
+ p->infinity = !y;
+ sp_1024_proj_point_add_qz1_32(rt, rt, p, t);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, t);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL) {
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(rt, 0, heap);
+
+ return err;
+}
+
+#ifdef FP_ECC
+#ifndef FP_ENTRIES
+ #define FP_ENTRIES 16
+#endif
+
+/* Cache entry - holds precomputation tables for a point. */
+typedef struct sp_cache_1024_t {
+ /* X ordinate of point that table was generated from. */
+ sp_digit x[32];
+ /* Y ordinate of point that table was generated from. */
+ sp_digit y[32];
+ /* Precomputation table for point. */
+ sp_table_entry_1024 table[16];
+ /* Count of entries in table. */
+ uint32_t cnt;
+ /* Point and table set in entry. */
+ int set;
+} sp_cache_1024_t;
+
+/* Cache of tables. */
+static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
+/* Index of last entry in cache. */
+static THREAD_LS_T int sp_cache_1024_last = -1;
+/* Cache has been initialized. */
+static THREAD_LS_T int sp_cache_1024_inited = 0;
+
+#ifndef HAVE_THREAD_LS
+ static volatile int initCacheMutex_1024 = 0;
+ static wolfSSL_Mutex sp_cache_1024_lock;
+#endif
+
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
+static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
+{
+ int i;
+ int j;
+ uint32_t least;
+
+ if (sp_cache_1024_inited == 0) {
+ for (i=0; i .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit qx_px[2 * 32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ qx_px = td + 8 * 32 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+
+ sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* h = t + 8 * 32;
+ sp_digit* r = t + 10 * 32;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_32(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_32(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_32(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_32(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_32(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_32(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 32;
+ sp_digit* pz2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* l = t + 8 * 32;
+ sp_digit* ty = t + 10 * 32;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_32(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_32(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_32(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* t2 = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_32(l, py, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_32(t2, t1, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_32(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* c = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_32(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_32(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_32(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 32;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_32(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_32(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 32 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_32(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_32(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_32(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, neg, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(neg, 1, NULL);
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_32(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
+ a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
+ a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = n-1; i >= 0; i--) {
+ r[j] |= (((sp_digit)a[i]) << s);
+ if (s >= 24U) {
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ r[++j] = (sp_digit)a[i] >> s;
+ s = 8U - s;
+ }
+ else {
+ s += 8U;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_32(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*32];
+ sp_digit t2d[2*32];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int32_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 32;
+ t2 = d + 2 * 32;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_32(t1, point->y);
+ (void)sp_1024_mod_32(t1, t1, p1024_mod);
+ sp_1024_sqr_32(t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ sp_1024_mul_32(t2, t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ (void)sp_1024_sub_32(t2, p1024_mod, t2);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_32(t1, p1024_mod);
+ sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(t1);
+ if (!sp_1024_iszero_32(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_32(pub, NULL);
+ }
+
+ sp_1024_point_free_32(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[32];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 32, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_32(pub->x) != 0) &&
+ (sp_1024_iszero_32(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_32(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) ||
+ (sp_1024_iszero_32(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_32(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_SP_ARM32_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c
index 7e29ce1bc..546ea4ac5 100644
--- a/wolfcrypt/src/sp_arm64.c
+++ b/wolfcrypt/src/sp_arm64.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -58,7 +58,8 @@
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j;
+ int i;
+ int j;
byte* d;
for (i = n - 1,j = 0; i >= 7; i -= 8) {
@@ -111,7 +112,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -145,7 +147,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -184,7 +188,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j;
+ int i;
+ int j;
for (i = 31, j = 0; i >= 0; i--) {
a[j++] = r[i] >> 56;
@@ -207,422 +212,412 @@ static void sp_2048_to_bin(sp_digit* r, byte* a)
*/
static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
{
- sp_digit tmp[8];
-
__asm__ __volatile__ (
- "ldp x9, x10, [%[a], 0]\n\t"
- "ldp x11, x12, [%[a], 16]\n\t"
- "ldp x13, x14, [%[a], 32]\n\t"
- "ldp x15, x16, [%[a], 48]\n\t"
- "ldp x17, x19, [%[b], 0]\n\t"
- "ldp x20, x21, [%[b], 16]\n\t"
- "ldp x22, x23, [%[b], 32]\n\t"
- "ldp x24, x25, [%[b], 48]\n\t"
+ "ldp x8, x9, [%[a], 0]\n\t"
+ "ldp x10, x11, [%[a], 16]\n\t"
+ "ldp x12, x13, [%[a], 32]\n\t"
+ "ldp x14, x15, [%[a], 48]\n\t"
+ "ldp x16, x17, [%[b], 0]\n\t"
+ "ldp x19, x20, [%[b], 16]\n\t"
+ "ldp x21, x22, [%[b], 32]\n\t"
+ "ldp x23, x24, [%[b], 48]\n\t"
"# A[0] * B[0]\n\t"
- "mul x4, x9, x17\n\t"
- "umulh x5, x9, x17\n\t"
- "str x4, [%[tmp]]\n\t"
+ "mul x3, x8, x16\n\t"
+ "umulh x4, x8, x16\n\t"
+ "str x3, [%[r]]\n\t"
"# A[0] * B[1]\n\t"
- "mul x7, x9, x19\n\t"
- "umulh x8, x9, x19\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x8, x17\n\t"
+ "umulh x7, x8, x17\n\t"
+ "adds x4, x4, x6\n\t"
"# A[1] * B[0]\n\t"
- "mul x7, x10, x17\n\t"
- "adc x6, xzr, x8\n\t"
- "umulh x8, x10, x17\n\t"
- "adds x5, x5, x7\n\t"
- "adcs x6, x6, x8\n\t"
- "str x5, [%[tmp], 8]\n\t"
- "adc x4, xzr, xzr\n\t"
+ "mul x6, x9, x16\n\t"
+ "adc x5, xzr, x7\n\t"
+ "umulh x7, x9, x16\n\t"
+ "adds x4, x4, x6\n\t"
+ "adcs x5, x5, x7\n\t"
+ "str x4, [%[r], 8]\n\t"
+ "adc x3, xzr, xzr\n\t"
"# A[0] * B[2]\n\t"
- "mul x7, x9, x20\n\t"
- "umulh x8, x9, x20\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x8, x19\n\t"
+ "umulh x7, x8, x19\n\t"
+ "adds x5, x5, x6\n\t"
"# A[1] * B[1]\n\t"
- "mul x7, x10, x19\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x10, x19\n\t"
- "adc x5, xzr, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x9, x17\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x9, x17\n\t"
+ "adc x4, xzr, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[2] * B[0]\n\t"
- "mul x7, x11, x17\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x11, x17\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "adcs x4, x4, x8\n\t"
- "str x6, [%[tmp], 16]\n\t"
- "adc x5, x5, xzr\n\t"
+ "mul x6, x10, x16\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x10, x16\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
+ "adcs x3, x3, x7\n\t"
+ "str x5, [%[r], 16]\n\t"
+ "adc x4, x4, xzr\n\t"
"# A[0] * B[3]\n\t"
- "mul x7, x9, x21\n\t"
- "umulh x8, x9, x21\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x8, x20\n\t"
+ "umulh x7, x8, x20\n\t"
+ "adds x3, x3, x6\n\t"
"# A[1] * B[2]\n\t"
- "mul x7, x10, x20\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x10, x20\n\t"
- "adc x6, xzr, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x9, x19\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x9, x19\n\t"
+ "adc x5, xzr, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[2] * B[1]\n\t"
- "mul x7, x11, x19\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x11, x19\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x10, x17\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x10, x17\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[3] * B[0]\n\t"
- "mul x7, x12, x17\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x12, x17\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "adcs x5, x5, x8\n\t"
- "str x4, [%[tmp], 24]\n\t"
- "adc x6, x6, xzr\n\t"
+ "mul x6, x11, x16\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x11, x16\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
+ "adcs x4, x4, x7\n\t"
+ "str x3, [%[r], 24]\n\t"
+ "adc x5, x5, xzr\n\t"
"# A[0] * B[4]\n\t"
- "mul x7, x9, x22\n\t"
- "umulh x8, x9, x22\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x8, x21\n\t"
+ "umulh x7, x8, x21\n\t"
+ "adds x4, x4, x6\n\t"
"# A[1] * B[3]\n\t"
- "mul x7, x10, x21\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x10, x21\n\t"
- "adc x4, xzr, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x9, x20\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x9, x20\n\t"
+ "adc x3, xzr, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[2] * B[2]\n\t"
- "mul x7, x11, x20\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x11, x20\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x10, x19\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x10, x19\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[3] * B[1]\n\t"
- "mul x7, x12, x19\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x12, x19\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x11, x17\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x11, x17\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[4] * B[0]\n\t"
- "mul x7, x13, x17\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x13, x17\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "adcs x6, x6, x8\n\t"
- "str x5, [%[tmp], 32]\n\t"
- "adc x4, x4, xzr\n\t"
+ "mul x6, x12, x16\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x12, x16\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "adcs x5, x5, x7\n\t"
+ "str x4, [%[r], 32]\n\t"
+ "adc x3, x3, xzr\n\t"
"# A[0] * B[5]\n\t"
- "mul x7, x9, x23\n\t"
- "umulh x8, x9, x23\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x8, x22\n\t"
+ "umulh x7, x8, x22\n\t"
+ "adds x5, x5, x6\n\t"
"# A[1] * B[4]\n\t"
- "mul x7, x10, x22\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x10, x22\n\t"
- "adc x5, xzr, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x9, x21\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x9, x21\n\t"
+ "adc x4, xzr, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[2] * B[3]\n\t"
- "mul x7, x11, x21\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x11, x21\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x10, x20\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x10, x20\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[3] * B[2]\n\t"
- "mul x7, x12, x20\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x12, x20\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x11, x19\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x11, x19\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[4] * B[1]\n\t"
- "mul x7, x13, x19\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x13, x19\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x12, x17\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x12, x17\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[5] * B[0]\n\t"
- "mul x7, x14, x17\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x14, x17\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "adcs x4, x4, x8\n\t"
- "str x6, [%[tmp], 40]\n\t"
- "adc x5, x5, xzr\n\t"
+ "mul x6, x13, x16\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x13, x16\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
+ "adcs x3, x3, x7\n\t"
+ "str x5, [%[r], 40]\n\t"
+ "adc x4, x4, xzr\n\t"
"# A[0] * B[6]\n\t"
- "mul x7, x9, x24\n\t"
- "umulh x8, x9, x24\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x8, x23\n\t"
+ "umulh x7, x8, x23\n\t"
+ "adds x3, x3, x6\n\t"
"# A[1] * B[5]\n\t"
- "mul x7, x10, x23\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x10, x23\n\t"
- "adc x6, xzr, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x9, x22\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x9, x22\n\t"
+ "adc x5, xzr, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[2] * B[4]\n\t"
- "mul x7, x11, x22\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x11, x22\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x10, x21\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x10, x21\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[3] * B[3]\n\t"
- "mul x7, x12, x21\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x12, x21\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x11, x20\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x11, x20\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[4] * B[2]\n\t"
- "mul x7, x13, x20\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x13, x20\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x12, x19\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x12, x19\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[5] * B[1]\n\t"
- "mul x7, x14, x19\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x14, x19\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x13, x17\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x13, x17\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
"# A[6] * B[0]\n\t"
- "mul x7, x15, x17\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x15, x17\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "adcs x5, x5, x8\n\t"
- "str x4, [%[tmp], 48]\n\t"
- "adc x6, x6, xzr\n\t"
+ "mul x6, x14, x16\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x14, x16\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
+ "adcs x4, x4, x7\n\t"
+ "str x3, [%[r], 48]\n\t"
+ "adc x5, x5, xzr\n\t"
"# A[0] * B[7]\n\t"
- "mul x7, x9, x25\n\t"
- "umulh x8, x9, x25\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x8, x24\n\t"
+ "umulh x7, x8, x24\n\t"
+ "adds x4, x4, x6\n\t"
"# A[1] * B[6]\n\t"
- "mul x7, x10, x24\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x10, x24\n\t"
- "adc x4, xzr, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x9, x23\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x9, x23\n\t"
+ "adc x3, xzr, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[2] * B[5]\n\t"
- "mul x7, x11, x23\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x11, x23\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x10, x22\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x10, x22\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[3] * B[4]\n\t"
- "mul x7, x12, x22\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x12, x22\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x11, x21\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x11, x21\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[4] * B[3]\n\t"
- "mul x7, x13, x21\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x13, x21\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x12, x20\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x12, x20\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[5] * B[2]\n\t"
- "mul x7, x14, x20\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x14, x20\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x13, x19\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x13, x19\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[6] * B[1]\n\t"
- "mul x7, x15, x19\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x15, x19\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
+ "mul x6, x14, x17\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x14, x17\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
"# A[7] * B[0]\n\t"
- "mul x7, x16, x17\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x16, x17\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "adcs x6, x6, x8\n\t"
- "str x5, [%[tmp], 56]\n\t"
- "adc x4, x4, xzr\n\t"
+ "mul x6, x15, x16\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x15, x16\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "adcs x5, x5, x7\n\t"
+ "str x4, [%[r], 56]\n\t"
+ "adc x3, x3, xzr\n\t"
"# A[1] * B[7]\n\t"
- "mul x7, x10, x25\n\t"
- "umulh x8, x10, x25\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x9, x24\n\t"
+ "umulh x7, x9, x24\n\t"
+ "adds x5, x5, x6\n\t"
"# A[2] * B[6]\n\t"
- "mul x7, x11, x24\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x11, x24\n\t"
- "adc x5, xzr, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x10, x23\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x10, x23\n\t"
+ "adc x4, xzr, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[3] * B[5]\n\t"
- "mul x7, x12, x23\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x12, x23\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x11, x22\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x11, x22\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[4] * B[4]\n\t"
- "mul x7, x13, x22\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x13, x22\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x12, x21\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x12, x21\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[5] * B[3]\n\t"
- "mul x7, x14, x21\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x14, x21\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x13, x20\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x13, x20\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[6] * B[2]\n\t"
- "mul x7, x15, x20\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x15, x20\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
+ "mul x6, x14, x19\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x14, x19\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
"# A[7] * B[1]\n\t"
- "mul x7, x16, x19\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x16, x19\n\t"
- "adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "adcs x4, x4, x8\n\t"
- "str x6, [%[r], 64]\n\t"
- "adc x5, x5, xzr\n\t"
+ "mul x6, x15, x17\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x15, x17\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
+ "adcs x3, x3, x7\n\t"
+ "str x5, [%[r], 64]\n\t"
+ "adc x4, x4, xzr\n\t"
"# A[2] * B[7]\n\t"
- "mul x7, x11, x25\n\t"
- "umulh x8, x11, x25\n\t"
- "adds x4, x4, x7\n\t"
+ "mul x6, x10, x24\n\t"
+ "umulh x7, x10, x24\n\t"
+ "adds x3, x3, x6\n\t"
"# A[3] * B[6]\n\t"
- "mul x7, x12, x24\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x12, x24\n\t"
- "adc x6, xzr, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "# A[4] * B[5]\n\t"
- "mul x7, x13, x23\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x13, x23\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "# A[5] * B[4]\n\t"
- "mul x7, x14, x22\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x14, x22\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "# A[6] * B[3]\n\t"
- "mul x7, x15, x21\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x15, x21\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "# A[7] * B[2]\n\t"
- "mul x7, x16, x20\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x16, x20\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "adcs x5, x5, x8\n\t"
- "str x4, [%[r], 72]\n\t"
- "adc x6, x6, xzr\n\t"
- "# A[3] * B[7]\n\t"
- "mul x7, x12, x25\n\t"
- "umulh x8, x12, x25\n\t"
- "adds x5, x5, x7\n\t"
- "# A[4] * B[6]\n\t"
- "mul x7, x13, x24\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x13, x24\n\t"
- "adc x4, xzr, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "# A[5] * B[5]\n\t"
- "mul x7, x14, x23\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x14, x23\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "# A[6] * B[4]\n\t"
- "mul x7, x15, x22\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x15, x22\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "# A[7] * B[3]\n\t"
- "mul x7, x16, x21\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x16, x21\n\t"
- "adc x4, x4, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "adcs x6, x6, x8\n\t"
- "str x5, [%[r], 80]\n\t"
- "adc x4, x4, xzr\n\t"
- "# A[4] * B[7]\n\t"
- "mul x7, x13, x25\n\t"
- "umulh x8, x13, x25\n\t"
- "adds x6, x6, x7\n\t"
- "# A[5] * B[6]\n\t"
- "mul x7, x14, x24\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x14, x24\n\t"
+ "mul x6, x11, x23\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x11, x23\n\t"
"adc x5, xzr, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "# A[6] * B[5]\n\t"
- "mul x7, x15, x23\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x15, x23\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[4] * B[5]\n\t"
+ "mul x6, x12, x22\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x12, x22\n\t"
"adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "# A[7] * B[4]\n\t"
- "mul x7, x16, x22\n\t"
- "adcs x4, x4, x8\n\t"
- "umulh x8, x16, x22\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[5] * B[4]\n\t"
+ "mul x6, x13, x21\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x13, x21\n\t"
"adc x5, x5, xzr\n\t"
- "adds x6, x6, x7\n\t"
- "adcs x4, x4, x8\n\t"
- "str x6, [%[r], 88]\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[6] * B[3]\n\t"
+ "mul x6, x14, x20\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x14, x20\n\t"
"adc x5, x5, xzr\n\t"
- "# A[5] * B[7]\n\t"
- "mul x7, x14, x25\n\t"
- "umulh x8, x14, x25\n\t"
- "adds x4, x4, x7\n\t"
- "# A[6] * B[6]\n\t"
- "mul x7, x15, x24\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x15, x24\n\t"
- "adc x6, xzr, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "# A[7] * B[5]\n\t"
- "mul x7, x16, x23\n\t"
- "adcs x5, x5, x8\n\t"
- "umulh x8, x16, x23\n\t"
- "adc x6, x6, xzr\n\t"
- "adds x4, x4, x7\n\t"
- "adcs x5, x5, x8\n\t"
- "str x4, [%[r], 96]\n\t"
- "adc x6, x6, xzr\n\t"
- "# A[6] * B[7]\n\t"
- "mul x7, x15, x25\n\t"
- "umulh x8, x15, x25\n\t"
- "adds x5, x5, x7\n\t"
- "# A[7] * B[6]\n\t"
- "mul x7, x16, x24\n\t"
- "adcs x6, x6, x8\n\t"
- "umulh x8, x16, x24\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[7] * B[2]\n\t"
+ "mul x6, x15, x19\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x15, x19\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
+ "adcs x4, x4, x7\n\t"
+ "str x3, [%[r], 72]\n\t"
+ "adc x5, x5, xzr\n\t"
+ "# A[3] * B[7]\n\t"
+ "mul x6, x11, x24\n\t"
+ "umulh x7, x11, x24\n\t"
+ "adds x4, x4, x6\n\t"
+ "# A[4] * B[6]\n\t"
+ "mul x6, x12, x23\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x12, x23\n\t"
+ "adc x3, xzr, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "# A[5] * B[5]\n\t"
+ "mul x6, x13, x22\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x13, x22\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "# A[6] * B[4]\n\t"
+ "mul x6, x14, x21\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x14, x21\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "# A[7] * B[3]\n\t"
+ "mul x6, x15, x20\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x15, x20\n\t"
+ "adc x3, x3, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "adcs x5, x5, x7\n\t"
+ "str x4, [%[r], 80]\n\t"
+ "adc x3, x3, xzr\n\t"
+ "# A[4] * B[7]\n\t"
+ "mul x6, x12, x24\n\t"
+ "umulh x7, x12, x24\n\t"
+ "adds x5, x5, x6\n\t"
+ "# A[5] * B[6]\n\t"
+ "mul x6, x13, x23\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x13, x23\n\t"
"adc x4, xzr, xzr\n\t"
- "adds x5, x5, x7\n\t"
- "adcs x6, x6, x8\n\t"
- "str x5, [%[r], 104]\n\t"
+ "adds x5, x5, x6\n\t"
+ "# A[6] * B[5]\n\t"
+ "mul x6, x14, x22\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x14, x22\n\t"
"adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
+ "# A[7] * B[4]\n\t"
+ "mul x6, x15, x21\n\t"
+ "adcs x3, x3, x7\n\t"
+ "umulh x7, x15, x21\n\t"
+ "adc x4, x4, xzr\n\t"
+ "adds x5, x5, x6\n\t"
+ "adcs x3, x3, x7\n\t"
+ "str x5, [%[r], 88]\n\t"
+ "adc x4, x4, xzr\n\t"
+ "# A[5] * B[7]\n\t"
+ "mul x6, x13, x24\n\t"
+ "umulh x7, x13, x24\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[6] * B[6]\n\t"
+ "mul x6, x14, x23\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x14, x23\n\t"
+ "adc x5, xzr, xzr\n\t"
+ "adds x3, x3, x6\n\t"
+ "# A[7] * B[5]\n\t"
+ "mul x6, x15, x22\n\t"
+ "adcs x4, x4, x7\n\t"
+ "umulh x7, x15, x22\n\t"
+ "adc x5, x5, xzr\n\t"
+ "adds x3, x3, x6\n\t"
+ "adcs x4, x4, x7\n\t"
+ "str x3, [%[r], 96]\n\t"
+ "adc x5, x5, xzr\n\t"
+ "# A[6] * B[7]\n\t"
+ "mul x6, x14, x24\n\t"
+ "umulh x7, x14, x24\n\t"
+ "adds x4, x4, x6\n\t"
+ "# A[7] * B[6]\n\t"
+ "mul x6, x15, x23\n\t"
+ "adcs x5, x5, x7\n\t"
+ "umulh x7, x15, x23\n\t"
+ "adc x3, xzr, xzr\n\t"
+ "adds x4, x4, x6\n\t"
+ "adcs x5, x5, x7\n\t"
+ "str x4, [%[r], 104]\n\t"
+ "adc x3, x3, xzr\n\t"
"# A[7] * B[7]\n\t"
- "mul x7, x16, x25\n\t"
- "umulh x8, x16, x25\n\t"
- "adds x6, x6, x7\n\t"
- "adc x4, x4, x8\n\t"
- "stp x6, x4, [%[r], 112]\n\t"
- "ldp x9, x10, [%[tmp], 0]\n\t"
- "ldp x11, x12, [%[tmp], 16]\n\t"
- "ldp x13, x14, [%[tmp], 32]\n\t"
- "ldp x15, x16, [%[tmp], 48]\n\t"
- "stp x9, x10, [%[r], 0]\n\t"
- "stp x11, x12, [%[r], 16]\n\t"
- "stp x13, x14, [%[r], 32]\n\t"
- "stp x15, x16, [%[r], 48]\n\t"
+ "mul x6, x15, x24\n\t"
+ "umulh x7, x15, x24\n\t"
+ "adds x5, x5, x6\n\t"
+ "adc x3, x3, x7\n\t"
+ "stp x5, x3, [%[r], 112]\n\t"
:
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
- : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25"
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b)
+ : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24"
);
}
@@ -1208,7 +1203,6 @@ SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
u += sp_2048_add_16(r + 8, r + 8, z1);
u += sp_2048_add_8(r + 16, r + 16, z2);
sp_2048_add_zero_8(r + 24, z2 + 8, u);
-
}
/* Sub b from a into a. (a -= b)
@@ -1629,7 +1623,6 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
u += sp_2048_add_32(r + 16, r + 16, z1);
u += sp_2048_add_16(r + 32, r + 32, z2);
sp_2048_add_zero_16(r + 48, z2 + 16, u);
-
}
#endif /* !WOLFSSL_SP_SMALL */
@@ -2033,7 +2026,7 @@ static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -2042,7 +2035,8 @@ static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -2052,7 +2046,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -2495,7 +2489,6 @@ static sp_digit sp_2048_cond_sub_16(sp_digit* r, const sp_digit* a, const sp_dig
SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m,
sp_digit mp)
{
- sp_digit ca = 0;
__asm__ __volatile__ (
"ldp x14, x15, [%[m], 0]\n\t"
@@ -2505,6 +2498,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m,
"ldp x23, x24, [%[m], 64]\n\t"
"ldp x25, x26, [%[m], 80]\n\t"
"ldp x27, x28, [%[m], 96]\n\t"
+ "mov x3, xzr\n\t"
"# i = 16\n\t"
"mov x4, 16\n\t"
"ldp x12, x13, [%[a], 0]\n\t"
@@ -2645,25 +2639,78 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m,
"adc x6, x6, xzr\n\t"
"umulh x8, x8, x9\n\t"
"adds x6, x6, x7\n\t"
- "adcs x8, x8, %[ca]\n\t"
+ "adcs x8, x8, x3\n\t"
"str x11, [%[a], 112]\n\t"
- "cset %[ca], cs\n\t"
+ "cset x3, cs\n\t"
"adds x10, x10, x6\n\t"
"ldr x11, [%[a], 128]\n\t"
"str x10, [%[a], 120]\n\t"
"adcs x11, x11, x8\n\t"
"str x11, [%[a], 128]\n\t"
- "adc %[ca], %[ca], xzr\n\t"
+ "adc x3, x3, xzr\n\t"
"subs x4, x4, 1\n\t"
"add %[a], %[a], 8\n\t"
"bne 1b\n\t"
- "stp x12, x13, [%[a], 0]\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "# Create mask\n\t"
+ "neg x3, x3\n\t"
+ "mov x9, %[a]\n\t"
+ "sub %[a], %[a], 128\n\t"
+ "# Subtract masked modulus\n\t"
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "and x14, x14, x3\n\t"
+ "ldp x11, x10, [x9, 16]\n\t"
+ "and x15, x15, x3\n\t"
+ "subs x12, x12, x14\n\t"
+ "and x16, x16, x3\n\t"
+ "sbcs x13, x13, x15\n\t"
+ "and x17, x17, x3\n\t"
+ "sbcs x11, x11, x16\n\t"
+ "stp x12, x13, [%[a], 0]\n\t"
+ "sbcs x10, x10, x17\n\t"
+ "stp x11, x10, [%[a], 16]\n\t"
+ "ldp x12, x13, [x9, 32]\n\t"
+ "and x19, x19, x3\n\t"
+ "ldp x11, x10, [x9, 48]\n\t"
+ "and x20, x20, x3\n\t"
+ "sbcs x12, x12, x19\n\t"
+ "and x21, x21, x3\n\t"
+ "sbcs x13, x13, x20\n\t"
+ "and x22, x22, x3\n\t"
+ "sbcs x11, x11, x21\n\t"
+ "stp x12, x13, [%[a], 32]\n\t"
+ "sbcs x10, x10, x22\n\t"
+ "stp x11, x10, [%[a], 48]\n\t"
+ "ldp x12, x13, [x9, 64]\n\t"
+ "and x23, x23, x3\n\t"
+ "ldp x11, x10, [x9, 80]\n\t"
+ "and x24, x24, x3\n\t"
+ "sbcs x12, x12, x23\n\t"
+ "and x25, x25, x3\n\t"
+ "sbcs x13, x13, x24\n\t"
+ "and x26, x26, x3\n\t"
+ "sbcs x11, x11, x25\n\t"
+ "stp x12, x13, [%[a], 64]\n\t"
+ "sbcs x10, x10, x26\n\t"
+ "stp x11, x10, [%[a], 80]\n\t"
+ "ldp x7, x8, [%[m], 112]\n\t"
+ "ldp x12, x13, [x9, 96]\n\t"
+ "and x27, x27, x3\n\t"
+ "ldp x11, x10, [x9, 112]\n\t"
+ "and x28, x28, x3\n\t"
+ "sbcs x12, x12, x27\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x28\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 96]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 112]\n\t"
+ : [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
);
- sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca);
}
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -2675,8 +2722,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_16(r, a, b);
sp_2048_mont_reduce_16(r, m, mp);
@@ -2689,8 +2736,8 @@ static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_16(r, a);
sp_2048_mont_reduce_16(r, m, mp);
@@ -3166,7 +3213,8 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3232,34 +3280,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n <<= 4;
c = 60;
}
else if (c < 4) {
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 60) & 0xf);
+ y = (byte)((n >> 60) & 0xf);
n <<= 4;
c -= 4;
}
@@ -3311,7 +3359,8 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3393,34 +3442,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else if (c < 5) {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -3451,7 +3500,7 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -3468,7 +3517,7 @@ static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m)
sp_2048_sub_in_place_32(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -3636,7 +3685,6 @@ static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig
SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
sp_digit mp)
{
- sp_digit ca = 0;
__asm__ __volatile__ (
"ldp x14, x15, [%[m], 0]\n\t"
@@ -3646,6 +3694,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"ldp x23, x24, [%[m], 64]\n\t"
"ldp x25, x26, [%[m], 80]\n\t"
"ldp x27, x28, [%[m], 96]\n\t"
+ "mov x3, xzr\n\t"
"# i = 32\n\t"
"mov x4, 32\n\t"
"ldp x12, x13, [%[a], 0]\n\t"
@@ -3946,25 +3995,134 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
"adc x6, x6, xzr\n\t"
"umulh x8, x8, x9\n\t"
"adds x6, x6, x7\n\t"
- "adcs x8, x8, %[ca]\n\t"
+ "adcs x8, x8, x3\n\t"
"str x11, [%[a], 240]\n\t"
- "cset %[ca], cs\n\t"
+ "cset x3, cs\n\t"
"adds x10, x10, x6\n\t"
"ldr x11, [%[a], 256]\n\t"
"str x10, [%[a], 248]\n\t"
"adcs x11, x11, x8\n\t"
"str x11, [%[a], 256]\n\t"
- "adc %[ca], %[ca], xzr\n\t"
+ "adc x3, x3, xzr\n\t"
"subs x4, x4, 1\n\t"
"add %[a], %[a], 8\n\t"
"bne 1b\n\t"
- "stp x12, x13, [%[a], 0]\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "# Create mask\n\t"
+ "neg x3, x3\n\t"
+ "mov x9, %[a]\n\t"
+ "sub %[a], %[a], 256\n\t"
+ "# Subtract masked modulus\n\t"
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "and x14, x14, x3\n\t"
+ "ldp x11, x10, [x9, 16]\n\t"
+ "and x15, x15, x3\n\t"
+ "subs x12, x12, x14\n\t"
+ "and x16, x16, x3\n\t"
+ "sbcs x13, x13, x15\n\t"
+ "and x17, x17, x3\n\t"
+ "sbcs x11, x11, x16\n\t"
+ "stp x12, x13, [%[a], 0]\n\t"
+ "sbcs x10, x10, x17\n\t"
+ "stp x11, x10, [%[a], 16]\n\t"
+ "ldp x12, x13, [x9, 32]\n\t"
+ "and x19, x19, x3\n\t"
+ "ldp x11, x10, [x9, 48]\n\t"
+ "and x20, x20, x3\n\t"
+ "sbcs x12, x12, x19\n\t"
+ "and x21, x21, x3\n\t"
+ "sbcs x13, x13, x20\n\t"
+ "and x22, x22, x3\n\t"
+ "sbcs x11, x11, x21\n\t"
+ "stp x12, x13, [%[a], 32]\n\t"
+ "sbcs x10, x10, x22\n\t"
+ "stp x11, x10, [%[a], 48]\n\t"
+ "ldp x12, x13, [x9, 64]\n\t"
+ "and x23, x23, x3\n\t"
+ "ldp x11, x10, [x9, 80]\n\t"
+ "and x24, x24, x3\n\t"
+ "sbcs x12, x12, x23\n\t"
+ "and x25, x25, x3\n\t"
+ "sbcs x13, x13, x24\n\t"
+ "and x26, x26, x3\n\t"
+ "sbcs x11, x11, x25\n\t"
+ "stp x12, x13, [%[a], 64]\n\t"
+ "sbcs x10, x10, x26\n\t"
+ "stp x11, x10, [%[a], 80]\n\t"
+ "ldp x7, x8, [%[m], 112]\n\t"
+ "ldp x12, x13, [x9, 96]\n\t"
+ "and x27, x27, x3\n\t"
+ "ldp x11, x10, [x9, 112]\n\t"
+ "and x28, x28, x3\n\t"
+ "sbcs x12, x12, x27\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x28\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 96]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 112]\n\t"
+ "ldp x5, x6, [%[m], 128]\n\t"
+ "ldp x7, x8, [%[m], 144]\n\t"
+ "ldp x12, x13, [x9, 128]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 144]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 128]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 144]\n\t"
+ "ldp x5, x6, [%[m], 160]\n\t"
+ "ldp x7, x8, [%[m], 176]\n\t"
+ "ldp x12, x13, [x9, 160]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 176]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 160]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 176]\n\t"
+ "ldp x5, x6, [%[m], 192]\n\t"
+ "ldp x7, x8, [%[m], 208]\n\t"
+ "ldp x12, x13, [x9, 192]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 208]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 192]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 208]\n\t"
+ "ldp x5, x6, [%[m], 224]\n\t"
+ "ldp x7, x8, [%[m], 240]\n\t"
+ "ldp x12, x13, [x9, 224]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 240]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 224]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 240]\n\t"
+ : [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
);
- sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
}
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -3976,8 +4134,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_32(r, a, b);
sp_2048_mont_reduce_32(r, m, mp);
@@ -3990,8 +4148,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_32(r, a);
sp_2048_mont_reduce_32(r, m, mp);
@@ -4631,7 +4789,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4697,34 +4856,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n <<= 4;
c = 60;
}
else if (c < 4) {
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 60) & 0xf);
+ y = (byte)((n >> 60) & 0xf);
n <<= 4;
c -= 4;
}
@@ -4776,7 +4935,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4858,34 +5018,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else if (c < 5) {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -4930,11 +5090,13 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[64], m[32], r[64];
+ sp_digit a[64];
+ sp_digit m[32];
+ sp_digit r[64];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -5173,9 +5335,9 @@ static sp_digit sp_2048_cond_add_16(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -5239,8 +5401,11 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[32 * 2];
- sp_digit p[16], q[16], dp[16];
- sp_digit tmpa[32], tmpb[32];
+ sp_digit p[16];
+ sp_digit q[16];
+ sp_digit dp[16];
+ sp_digit tmpa[32];
+ sp_digit tmpb[32];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -5337,7 +5502,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -5360,17 +5525,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 32;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 32; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -5383,14 +5550,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 32; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -5417,10 +5586,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5680,10 +5852,12 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5718,34 +5892,34 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
- sp_2048_lshift_32(r, norm, (byte)y);
+ sp_2048_lshift_32(r, norm, y);
for (; i>=0 || c>=6; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -5757,7 +5931,7 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
sp_2048_mont_sqr_32(r, r, m, mp);
sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_lshift_32(r, r, (byte)y);
+ sp_2048_lshift_32(r, r, y);
sp_2048_mul_d_32(tmp, norm, r[32]);
r[32] = 0;
o = sp_2048_add_32(r, r, tmp);
@@ -5793,11 +5967,13 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
word32 i;
@@ -5832,6 +6008,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -5853,10 +6030,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[32], e[16], m[16];
+ sp_digit b[32];
+ sp_digit e[16];
+ sp_digit m[16];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5893,7 +6073,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -5907,7 +6087,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j;
+ int i;
+ int j;
byte* d;
for (i = n - 1,j = 0; i >= 7; i -= 8) {
@@ -5960,7 +6141,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -5994,7 +6176,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -6033,7 +6217,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j;
+ int i;
+ int j;
for (i = 47, j = 0; i >= 0; i--) {
a[j++] = r[i] >> 56;
@@ -8130,7 +8315,6 @@ SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
u += sp_3072_add_24(r + 12, r + 12, z1);
u += sp_3072_add_12(r + 24, r + 24, z2);
sp_3072_add_zero_12(r + 36, z2 + 12, u);
-
}
/* Sub b from a into a. (a -= b)
@@ -8665,7 +8849,6 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
u += sp_3072_add_48(r + 24, r + 24, z1);
u += sp_3072_add_24(r + 48, r + 48, z2);
sp_3072_add_zero_24(r + 72, z2 + 24, u);
-
}
#endif /* !WOLFSSL_SP_SMALL */
@@ -9069,7 +9252,7 @@ static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -9078,7 +9261,8 @@ static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -9088,7 +9272,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -9695,7 +9879,6 @@ static sp_digit sp_3072_cond_sub_24(sp_digit* r, const sp_digit* a, const sp_dig
SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m,
sp_digit mp)
{
- sp_digit ca = 0;
__asm__ __volatile__ (
"ldp x14, x15, [%[m], 0]\n\t"
@@ -9705,6 +9888,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m,
"ldp x23, x24, [%[m], 64]\n\t"
"ldp x25, x26, [%[m], 80]\n\t"
"ldp x27, x28, [%[m], 96]\n\t"
+ "mov x3, xzr\n\t"
"# i = 24\n\t"
"mov x4, 24\n\t"
"ldp x12, x13, [%[a], 0]\n\t"
@@ -9925,25 +10109,106 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m,
"adc x6, x6, xzr\n\t"
"umulh x8, x8, x9\n\t"
"adds x6, x6, x7\n\t"
- "adcs x8, x8, %[ca]\n\t"
+ "adcs x8, x8, x3\n\t"
"str x11, [%[a], 176]\n\t"
- "cset %[ca], cs\n\t"
+ "cset x3, cs\n\t"
"adds x10, x10, x6\n\t"
"ldr x11, [%[a], 192]\n\t"
"str x10, [%[a], 184]\n\t"
"adcs x11, x11, x8\n\t"
"str x11, [%[a], 192]\n\t"
- "adc %[ca], %[ca], xzr\n\t"
+ "adc x3, x3, xzr\n\t"
"subs x4, x4, 1\n\t"
"add %[a], %[a], 8\n\t"
"bne 1b\n\t"
- "stp x12, x13, [%[a], 0]\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "# Create mask\n\t"
+ "neg x3, x3\n\t"
+ "mov x9, %[a]\n\t"
+ "sub %[a], %[a], 192\n\t"
+ "# Subtract masked modulus\n\t"
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "and x14, x14, x3\n\t"
+ "ldp x11, x10, [x9, 16]\n\t"
+ "and x15, x15, x3\n\t"
+ "subs x12, x12, x14\n\t"
+ "and x16, x16, x3\n\t"
+ "sbcs x13, x13, x15\n\t"
+ "and x17, x17, x3\n\t"
+ "sbcs x11, x11, x16\n\t"
+ "stp x12, x13, [%[a], 0]\n\t"
+ "sbcs x10, x10, x17\n\t"
+ "stp x11, x10, [%[a], 16]\n\t"
+ "ldp x12, x13, [x9, 32]\n\t"
+ "and x19, x19, x3\n\t"
+ "ldp x11, x10, [x9, 48]\n\t"
+ "and x20, x20, x3\n\t"
+ "sbcs x12, x12, x19\n\t"
+ "and x21, x21, x3\n\t"
+ "sbcs x13, x13, x20\n\t"
+ "and x22, x22, x3\n\t"
+ "sbcs x11, x11, x21\n\t"
+ "stp x12, x13, [%[a], 32]\n\t"
+ "sbcs x10, x10, x22\n\t"
+ "stp x11, x10, [%[a], 48]\n\t"
+ "ldp x12, x13, [x9, 64]\n\t"
+ "and x23, x23, x3\n\t"
+ "ldp x11, x10, [x9, 80]\n\t"
+ "and x24, x24, x3\n\t"
+ "sbcs x12, x12, x23\n\t"
+ "and x25, x25, x3\n\t"
+ "sbcs x13, x13, x24\n\t"
+ "and x26, x26, x3\n\t"
+ "sbcs x11, x11, x25\n\t"
+ "stp x12, x13, [%[a], 64]\n\t"
+ "sbcs x10, x10, x26\n\t"
+ "stp x11, x10, [%[a], 80]\n\t"
+ "ldp x7, x8, [%[m], 112]\n\t"
+ "ldp x12, x13, [x9, 96]\n\t"
+ "and x27, x27, x3\n\t"
+ "ldp x11, x10, [x9, 112]\n\t"
+ "and x28, x28, x3\n\t"
+ "sbcs x12, x12, x27\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x28\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 96]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 112]\n\t"
+ "ldp x5, x6, [%[m], 128]\n\t"
+ "ldp x7, x8, [%[m], 144]\n\t"
+ "ldp x12, x13, [x9, 128]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 144]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 128]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 144]\n\t"
+ "ldp x5, x6, [%[m], 160]\n\t"
+ "ldp x7, x8, [%[m], 176]\n\t"
+ "ldp x12, x13, [x9, 160]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 176]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 160]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 176]\n\t"
+ : [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
);
- sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca);
}
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -9955,8 +10220,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_24(r, a, b);
sp_3072_mont_reduce_24(r, m, mp);
@@ -9969,8 +10234,8 @@ static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_24(r, a);
sp_3072_mont_reduce_24(r, m, mp);
@@ -10570,7 +10835,8 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10636,34 +10902,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n <<= 4;
c = 60;
}
else if (c < 4) {
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 60) & 0xf);
+ y = (byte)((n >> 60) & 0xf);
n <<= 4;
c -= 4;
}
@@ -10715,7 +10981,8 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10797,34 +11064,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else if (c < 5) {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -10855,7 +11122,7 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -10872,7 +11139,7 @@ static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m)
sp_3072_sub_in_place_48(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -11096,7 +11363,6 @@ static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_dig
SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
sp_digit mp)
{
- sp_digit ca = 0;
__asm__ __volatile__ (
"ldp x14, x15, [%[m], 0]\n\t"
@@ -11106,6 +11372,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"ldp x23, x24, [%[m], 64]\n\t"
"ldp x25, x26, [%[m], 80]\n\t"
"ldp x27, x28, [%[m], 96]\n\t"
+ "mov x3, xzr\n\t"
"# i = 48\n\t"
"mov x4, 48\n\t"
"ldp x12, x13, [%[a], 0]\n\t"
@@ -11566,25 +11833,190 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
"adc x6, x6, xzr\n\t"
"umulh x8, x8, x9\n\t"
"adds x6, x6, x7\n\t"
- "adcs x8, x8, %[ca]\n\t"
+ "adcs x8, x8, x3\n\t"
"str x11, [%[a], 368]\n\t"
- "cset %[ca], cs\n\t"
+ "cset x3, cs\n\t"
"adds x10, x10, x6\n\t"
"ldr x11, [%[a], 384]\n\t"
"str x10, [%[a], 376]\n\t"
"adcs x11, x11, x8\n\t"
"str x11, [%[a], 384]\n\t"
- "adc %[ca], %[ca], xzr\n\t"
+ "adc x3, x3, xzr\n\t"
"subs x4, x4, 1\n\t"
"add %[a], %[a], 8\n\t"
"bne 1b\n\t"
- "stp x12, x13, [%[a], 0]\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "# Create mask\n\t"
+ "neg x3, x3\n\t"
+ "mov x9, %[a]\n\t"
+ "sub %[a], %[a], 384\n\t"
+ "# Subtract masked modulus\n\t"
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "and x14, x14, x3\n\t"
+ "ldp x11, x10, [x9, 16]\n\t"
+ "and x15, x15, x3\n\t"
+ "subs x12, x12, x14\n\t"
+ "and x16, x16, x3\n\t"
+ "sbcs x13, x13, x15\n\t"
+ "and x17, x17, x3\n\t"
+ "sbcs x11, x11, x16\n\t"
+ "stp x12, x13, [%[a], 0]\n\t"
+ "sbcs x10, x10, x17\n\t"
+ "stp x11, x10, [%[a], 16]\n\t"
+ "ldp x12, x13, [x9, 32]\n\t"
+ "and x19, x19, x3\n\t"
+ "ldp x11, x10, [x9, 48]\n\t"
+ "and x20, x20, x3\n\t"
+ "sbcs x12, x12, x19\n\t"
+ "and x21, x21, x3\n\t"
+ "sbcs x13, x13, x20\n\t"
+ "and x22, x22, x3\n\t"
+ "sbcs x11, x11, x21\n\t"
+ "stp x12, x13, [%[a], 32]\n\t"
+ "sbcs x10, x10, x22\n\t"
+ "stp x11, x10, [%[a], 48]\n\t"
+ "ldp x12, x13, [x9, 64]\n\t"
+ "and x23, x23, x3\n\t"
+ "ldp x11, x10, [x9, 80]\n\t"
+ "and x24, x24, x3\n\t"
+ "sbcs x12, x12, x23\n\t"
+ "and x25, x25, x3\n\t"
+ "sbcs x13, x13, x24\n\t"
+ "and x26, x26, x3\n\t"
+ "sbcs x11, x11, x25\n\t"
+ "stp x12, x13, [%[a], 64]\n\t"
+ "sbcs x10, x10, x26\n\t"
+ "stp x11, x10, [%[a], 80]\n\t"
+ "ldp x7, x8, [%[m], 112]\n\t"
+ "ldp x12, x13, [x9, 96]\n\t"
+ "and x27, x27, x3\n\t"
+ "ldp x11, x10, [x9, 112]\n\t"
+ "and x28, x28, x3\n\t"
+ "sbcs x12, x12, x27\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x28\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 96]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 112]\n\t"
+ "ldp x5, x6, [%[m], 128]\n\t"
+ "ldp x7, x8, [%[m], 144]\n\t"
+ "ldp x12, x13, [x9, 128]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 144]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 128]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 144]\n\t"
+ "ldp x5, x6, [%[m], 160]\n\t"
+ "ldp x7, x8, [%[m], 176]\n\t"
+ "ldp x12, x13, [x9, 160]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 176]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 160]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 176]\n\t"
+ "ldp x5, x6, [%[m], 192]\n\t"
+ "ldp x7, x8, [%[m], 208]\n\t"
+ "ldp x12, x13, [x9, 192]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 208]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 192]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 208]\n\t"
+ "ldp x5, x6, [%[m], 224]\n\t"
+ "ldp x7, x8, [%[m], 240]\n\t"
+ "ldp x12, x13, [x9, 224]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 240]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 224]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 240]\n\t"
+ "ldp x5, x6, [%[m], 256]\n\t"
+ "ldp x7, x8, [%[m], 272]\n\t"
+ "ldp x12, x13, [x9, 256]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 272]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 256]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 272]\n\t"
+ "ldp x5, x6, [%[m], 288]\n\t"
+ "ldp x7, x8, [%[m], 304]\n\t"
+ "ldp x12, x13, [x9, 288]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 304]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 288]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 304]\n\t"
+ "ldp x5, x6, [%[m], 320]\n\t"
+ "ldp x7, x8, [%[m], 336]\n\t"
+ "ldp x12, x13, [x9, 320]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 336]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 320]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 336]\n\t"
+ "ldp x5, x6, [%[m], 352]\n\t"
+ "ldp x7, x8, [%[m], 368]\n\t"
+ "ldp x12, x13, [x9, 352]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 368]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 352]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 368]\n\t"
+ : [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
);
- sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
}
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -11596,8 +12028,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_48(r, a, b);
sp_3072_mont_reduce_48(r, m, mp);
@@ -11610,8 +12042,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_48(r, a);
sp_3072_mont_reduce_48(r, m, mp);
@@ -12403,7 +12835,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12469,34 +12902,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n <<= 4;
c = 60;
}
else if (c < 4) {
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 60) & 0xf);
+ y = (byte)((n >> 60) & 0xf);
n <<= 4;
c -= 4;
}
@@ -12548,7 +12981,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12630,34 +13064,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else if (c < 5) {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -12702,11 +13136,13 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[96], m[48], r[96];
+ sp_digit a[96];
+ sp_digit m[48];
+ sp_digit r[96];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -12973,9 +13409,9 @@ static sp_digit sp_3072_cond_add_24(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -13039,8 +13475,11 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[48 * 2];
- sp_digit p[24], q[24], dp[24];
- sp_digit tmpa[48], tmpb[48];
+ sp_digit p[24];
+ sp_digit q[24];
+ sp_digit dp[24];
+ sp_digit tmpa[48];
+ sp_digit tmpb[48];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -13137,7 +13576,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -13160,17 +13599,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 48;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 48; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -13183,14 +13624,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 48; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -13217,10 +13660,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -13576,10 +14022,12 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -13614,34 +14062,34 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
- sp_3072_lshift_48(r, norm, (byte)y);
+ sp_3072_lshift_48(r, norm, y);
for (; i>=0 || c>=6; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -13653,7 +14101,7 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
sp_3072_mont_sqr_48(r, r, m, mp);
sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_lshift_48(r, r, (byte)y);
+ sp_3072_lshift_48(r, r, y);
sp_3072_mul_d_48(tmp, norm, r[48]);
r[48] = 0;
o = sp_3072_add_48(r, r, tmp);
@@ -13689,11 +14137,13 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
word32 i;
@@ -13728,6 +14178,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -13749,10 +14200,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[48], e[24], m[24];
+ sp_digit b[48];
+ sp_digit e[24];
+ sp_digit m[24];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -13789,7 +14243,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -13803,7 +14257,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j;
+ int i;
+ int j;
byte* d;
for (i = n - 1,j = 0; i >= 7; i -= 8) {
@@ -13856,7 +14311,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -13890,7 +14346,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -13929,7 +14387,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j;
+ int i;
+ int j;
for (i = 63, j = 0; i >= 0; i--) {
a[j++] = r[i] >> 56;
@@ -14659,7 +15118,6 @@ SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a)
u += sp_4096_add_64(r + 32, r + 32, z1);
u += sp_4096_add_32(r + 64, r + 64, z2);
sp_4096_add_zero_32(r + 96, z2 + 32, u);
-
}
#endif /* !WOLFSSL_SP_SMALL */
@@ -14861,7 +15319,8 @@ static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -14871,7 +15330,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -15475,7 +15934,7 @@ static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m)
sp_4096_sub_in_place_64(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -15755,7 +16214,6 @@ static sp_digit sp_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_dig
SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m,
sp_digit mp)
{
- sp_digit ca = 0;
__asm__ __volatile__ (
"ldp x14, x15, [%[m], 0]\n\t"
@@ -15765,6 +16223,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m,
"ldp x23, x24, [%[m], 64]\n\t"
"ldp x25, x26, [%[m], 80]\n\t"
"ldp x27, x28, [%[m], 96]\n\t"
+ "mov x3, xzr\n\t"
"# i = 64\n\t"
"mov x4, 64\n\t"
"ldp x12, x13, [%[a], 0]\n\t"
@@ -16385,25 +16844,246 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m,
"adc x6, x6, xzr\n\t"
"umulh x8, x8, x9\n\t"
"adds x6, x6, x7\n\t"
- "adcs x8, x8, %[ca]\n\t"
+ "adcs x8, x8, x3\n\t"
"str x11, [%[a], 496]\n\t"
- "cset %[ca], cs\n\t"
+ "cset x3, cs\n\t"
"adds x10, x10, x6\n\t"
"ldr x11, [%[a], 512]\n\t"
"str x10, [%[a], 504]\n\t"
"adcs x11, x11, x8\n\t"
"str x11, [%[a], 512]\n\t"
- "adc %[ca], %[ca], xzr\n\t"
+ "adc x3, x3, xzr\n\t"
"subs x4, x4, 1\n\t"
"add %[a], %[a], 8\n\t"
"bne 1b\n\t"
- "stp x12, x13, [%[a], 0]\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "# Create mask\n\t"
+ "neg x3, x3\n\t"
+ "mov x9, %[a]\n\t"
+ "sub %[a], %[a], 512\n\t"
+ "# Subtract masked modulus\n\t"
+ "# x12 and x13 hold a[0] and a[1]\n\t"
+ "and x14, x14, x3\n\t"
+ "ldp x11, x10, [x9, 16]\n\t"
+ "and x15, x15, x3\n\t"
+ "subs x12, x12, x14\n\t"
+ "and x16, x16, x3\n\t"
+ "sbcs x13, x13, x15\n\t"
+ "and x17, x17, x3\n\t"
+ "sbcs x11, x11, x16\n\t"
+ "stp x12, x13, [%[a], 0]\n\t"
+ "sbcs x10, x10, x17\n\t"
+ "stp x11, x10, [%[a], 16]\n\t"
+ "ldp x12, x13, [x9, 32]\n\t"
+ "and x19, x19, x3\n\t"
+ "ldp x11, x10, [x9, 48]\n\t"
+ "and x20, x20, x3\n\t"
+ "sbcs x12, x12, x19\n\t"
+ "and x21, x21, x3\n\t"
+ "sbcs x13, x13, x20\n\t"
+ "and x22, x22, x3\n\t"
+ "sbcs x11, x11, x21\n\t"
+ "stp x12, x13, [%[a], 32]\n\t"
+ "sbcs x10, x10, x22\n\t"
+ "stp x11, x10, [%[a], 48]\n\t"
+ "ldp x12, x13, [x9, 64]\n\t"
+ "and x23, x23, x3\n\t"
+ "ldp x11, x10, [x9, 80]\n\t"
+ "and x24, x24, x3\n\t"
+ "sbcs x12, x12, x23\n\t"
+ "and x25, x25, x3\n\t"
+ "sbcs x13, x13, x24\n\t"
+ "and x26, x26, x3\n\t"
+ "sbcs x11, x11, x25\n\t"
+ "stp x12, x13, [%[a], 64]\n\t"
+ "sbcs x10, x10, x26\n\t"
+ "stp x11, x10, [%[a], 80]\n\t"
+ "ldp x7, x8, [%[m], 112]\n\t"
+ "ldp x12, x13, [x9, 96]\n\t"
+ "and x27, x27, x3\n\t"
+ "ldp x11, x10, [x9, 112]\n\t"
+ "and x28, x28, x3\n\t"
+ "sbcs x12, x12, x27\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x28\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 96]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 112]\n\t"
+ "ldp x5, x6, [%[m], 128]\n\t"
+ "ldp x7, x8, [%[m], 144]\n\t"
+ "ldp x12, x13, [x9, 128]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 144]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 128]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 144]\n\t"
+ "ldp x5, x6, [%[m], 160]\n\t"
+ "ldp x7, x8, [%[m], 176]\n\t"
+ "ldp x12, x13, [x9, 160]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 176]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 160]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 176]\n\t"
+ "ldp x5, x6, [%[m], 192]\n\t"
+ "ldp x7, x8, [%[m], 208]\n\t"
+ "ldp x12, x13, [x9, 192]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 208]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 192]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 208]\n\t"
+ "ldp x5, x6, [%[m], 224]\n\t"
+ "ldp x7, x8, [%[m], 240]\n\t"
+ "ldp x12, x13, [x9, 224]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 240]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 224]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 240]\n\t"
+ "ldp x5, x6, [%[m], 256]\n\t"
+ "ldp x7, x8, [%[m], 272]\n\t"
+ "ldp x12, x13, [x9, 256]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 272]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 256]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 272]\n\t"
+ "ldp x5, x6, [%[m], 288]\n\t"
+ "ldp x7, x8, [%[m], 304]\n\t"
+ "ldp x12, x13, [x9, 288]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 304]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 288]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 304]\n\t"
+ "ldp x5, x6, [%[m], 320]\n\t"
+ "ldp x7, x8, [%[m], 336]\n\t"
+ "ldp x12, x13, [x9, 320]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 336]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 320]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 336]\n\t"
+ "ldp x5, x6, [%[m], 352]\n\t"
+ "ldp x7, x8, [%[m], 368]\n\t"
+ "ldp x12, x13, [x9, 352]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 368]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 352]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 368]\n\t"
+ "ldp x5, x6, [%[m], 384]\n\t"
+ "ldp x7, x8, [%[m], 400]\n\t"
+ "ldp x12, x13, [x9, 384]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 400]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 384]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 400]\n\t"
+ "ldp x5, x6, [%[m], 416]\n\t"
+ "ldp x7, x8, [%[m], 432]\n\t"
+ "ldp x12, x13, [x9, 416]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 432]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 416]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 432]\n\t"
+ "ldp x5, x6, [%[m], 448]\n\t"
+ "ldp x7, x8, [%[m], 464]\n\t"
+ "ldp x12, x13, [x9, 448]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 464]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 448]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 464]\n\t"
+ "ldp x5, x6, [%[m], 480]\n\t"
+ "ldp x7, x8, [%[m], 496]\n\t"
+ "ldp x12, x13, [x9, 480]\n\t"
+ "and x5, x5, x3\n\t"
+ "ldp x11, x10, [x9, 496]\n\t"
+ "and x6, x6, x3\n\t"
+ "sbcs x12, x12, x5\n\t"
+ "and x7, x7, x3\n\t"
+ "sbcs x13, x13, x6\n\t"
+ "and x8, x8, x3\n\t"
+ "sbcs x11, x11, x7\n\t"
+ "stp x12, x13, [%[a], 480]\n\t"
+ "sbcs x10, x10, x8\n\t"
+ "stp x11, x10, [%[a], 496]\n\t"
+ : [a] "+r" (a)
: [m] "r" (m), [mp] "r" (mp)
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
);
- sp_4096_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca);
}
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -16415,8 +17095,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_64(r, a, b);
sp_4096_mont_reduce_64(r, m, mp);
@@ -16429,8 +17109,8 @@ static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_64(r, a);
sp_4096_mont_reduce_64(r, m, mp);
@@ -17374,7 +18054,8 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -17440,34 +18121,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n <<= 4;
c = 60;
}
else if (c < 4) {
- y = (int)(n >> 60);
+ y = (byte)(n >> 60);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 60) & 0xf);
+ y = (byte)((n >> 60) & 0xf);
n <<= 4;
c -= 4;
}
@@ -17519,7 +18200,8 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -17601,34 +18283,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else if (c < 5) {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -17673,11 +18355,13 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[128], m[64], r[128];
+ sp_digit a[128];
+ sp_digit m[64];
+ sp_digit r[128];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -17972,9 +18656,9 @@ static sp_digit sp_4096_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -18038,8 +18722,11 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[64 * 2];
- sp_digit p[32], q[32], dp[32];
- sp_digit tmpa[64], tmpb[64];
+ sp_digit p[32];
+ sp_digit q[32];
+ sp_digit dp[32];
+ sp_digit tmpa[64];
+ sp_digit tmpb[64];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -18136,7 +18823,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -18159,17 +18846,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 64;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -18182,14 +18871,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -18216,10 +18907,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -18671,10 +19365,12 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -18709,34 +19405,34 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
- sp_4096_lshift_64(r, norm, (byte)y);
+ sp_4096_lshift_64(r, norm, y);
for (; i>=0 || c>=6; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -18748,7 +19444,7 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_4096_mont_sqr_64(r, r, m, mp);
sp_4096_mont_sqr_64(r, r, m, mp);
- sp_4096_lshift_64(r, r, (byte)y);
+ sp_4096_lshift_64(r, r, y);
sp_4096_mul_d_64(tmp, norm, r[64]);
r[64] = 0;
o = sp_4096_add_64(r, r, tmp);
@@ -18784,11 +19480,13 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
word32 i;
@@ -18823,6 +19521,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -18835,19 +19534,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 4];
+ /* Y ordinate of point. */
sp_digit y[2 * 4];
+ /* Z ordinate of point. */
sp_digit z[2 * 4];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -18919,7 +19622,320 @@ static const sp_digit p256_b[4] = {
};
#endif
-static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p)
+#ifdef WOLFSSL_SP_SMALL
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ sp_digit tmp[8];
+
+ __asm__ __volatile__ (
+ "mov x5, 0\n\t"
+ "mov x6, 0\n\t"
+ "mov x7, 0\n\t"
+ "mov x8, 0\n\t"
+ "\n1:\n\t"
+ "subs x3, x5, 24\n\t"
+ "csel x3, xzr, x3, cc\n\t"
+ "sub x4, x5, x3\n\t"
+ "\n2:\n\t"
+ "ldr x10, [%[a], x3]\n\t"
+ "ldr x11, [%[b], x4]\n\t"
+ "mul x9, x10, x11\n\t"
+ "umulh x10, x10, x11\n\t"
+ "adds x6, x6, x9\n\t"
+ "adcs x7, x7, x10\n\t"
+ "adc x8, x8, xzr\n\t"
+ "add x3, x3, #8\n\t"
+ "sub x4, x4, #8\n\t"
+ "cmp x3, 32\n\t"
+ "b.eq 3f\n\t"
+ "cmp x3, x5\n\t"
+ "b.le 2b\n\t"
+ "\n3:\n\t"
+ "str x6, [%[r], x5]\n\t"
+ "mov x6, x7\n\t"
+ "mov x7, x8\n\t"
+ "mov x8, #0\n\t"
+ "add x5, x5, #8\n\t"
+ "cmp x5, 48\n\t"
+ "b.le 1b\n\t"
+ "str x6, [%[r], x5]\n\t"
+ :
+ : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
+ : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
+ );
+
+ XMEMCPY(r, tmp, sizeof(tmp));
+}
+
+#else
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b)
+{
+ sp_digit tmp[4];
+
+ __asm__ __volatile__ (
+ "ldp x16, x17, [%[a], 0]\n\t"
+ "ldp x21, x22, [%[b], 0]\n\t"
+ "# A[0] * B[0]\n\t"
+ "mul x8, x16, x21\n\t"
+ "ldr x19, [%[a], 16]\n\t"
+ "umulh x9, x16, x21\n\t"
+ "ldr x23, [%[b], 16]\n\t"
+ "# A[0] * B[1]\n\t"
+ "mul x4, x16, x22\n\t"
+ "ldr x20, [%[a], 24]\n\t"
+ "umulh x5, x16, x22\n\t"
+ "ldr x24, [%[b], 24]\n\t"
+ "adds x9, x9, x4\n\t"
+ "# A[1] * B[0]\n\t"
+ "mul x4, x17, x21\n\t"
+ "adc x10, xzr, x5\n\t"
+ "umulh x5, x17, x21\n\t"
+ "adds x9, x9, x4\n\t"
+ "# A[0] * B[2]\n\t"
+ "mul x4, x16, x23\n\t"
+ "adcs x10, x10, x5\n\t"
+ "umulh x5, x16, x23\n\t"
+ "adc x11, xzr, xzr\n\t"
+ "adds x10, x10, x4\n\t"
+ "# A[1] * B[1]\n\t"
+ "mul x4, x17, x22\n\t"
+ "adc x11, x11, x5\n\t"
+ "umulh x5, x17, x22\n\t"
+ "adds x10, x10, x4\n\t"
+ "# A[2] * B[0]\n\t"
+ "mul x4, x19, x21\n\t"
+ "adcs x11, x11, x5\n\t"
+ "umulh x5, x19, x21\n\t"
+ "adc x12, xzr, xzr\n\t"
+ "adds x10, x10, x4\n\t"
+ "# A[0] * B[3]\n\t"
+ "mul x4, x16, x24\n\t"
+ "adcs x11, x11, x5\n\t"
+ "umulh x5, x16, x24\n\t"
+ "adc x12, x12, xzr\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[1] * B[2]\n\t"
+ "mul x4, x17, x23\n\t"
+ "adcs x12, x12, x5\n\t"
+ "umulh x5, x17, x23\n\t"
+ "adc x13, xzr, xzr\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[2] * B[1]\n\t"
+ "mul x4, x19, x22\n\t"
+ "adcs x12, x12, x5\n\t"
+ "umulh x5, x19, x22\n\t"
+ "adc x13, x13, xzr\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[3] * B[0]\n\t"
+ "mul x4, x20, x21\n\t"
+ "adcs x12, x12, x5\n\t"
+ "umulh x5, x20, x21\n\t"
+ "adc x13, x13, xzr\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[1] * B[3]\n\t"
+ "mul x4, x17, x24\n\t"
+ "adcs x12, x12, x5\n\t"
+ "umulh x5, x17, x24\n\t"
+ "adc x13, x13, xzr\n\t"
+ "adds x12, x12, x4\n\t"
+ "# A[2] * B[2]\n\t"
+ "mul x4, x19, x23\n\t"
+ "adcs x13, x13, x5\n\t"
+ "umulh x5, x19, x23\n\t"
+ "adc x14, xzr, xzr\n\t"
+ "adds x12, x12, x4\n\t"
+ "# A[3] * B[1]\n\t"
+ "mul x4, x20, x22\n\t"
+ "adcs x13, x13, x5\n\t"
+ "umulh x5, x20, x22\n\t"
+ "adc x14, x14, xzr\n\t"
+ "adds x12, x12, x4\n\t"
+ "# A[2] * B[3]\n\t"
+ "mul x4, x19, x24\n\t"
+ "adcs x13, x13, x5\n\t"
+ "umulh x5, x19, x24\n\t"
+ "adc x14, x14, xzr\n\t"
+ "adds x13, x13, x4\n\t"
+ "# A[3] * B[2]\n\t"
+ "mul x4, x20, x23\n\t"
+ "adcs x14, x14, x5\n\t"
+ "umulh x5, x20, x23\n\t"
+ "adc x15, xzr, xzr\n\t"
+ "adds x13, x13, x4\n\t"
+ "# A[3] * B[3]\n\t"
+ "mul x4, x20, x24\n\t"
+ "adcs x14, x14, x5\n\t"
+ "umulh x5, x20, x24\n\t"
+ "adc x15, x15, xzr\n\t"
+ "adds x14, x14, x4\n\t"
+ "adc x15, x15, x5\n\t"
+ "stp x8, x9, [%[r], 0]\n\t"
+ "stp x10, x11, [%[r], 16]\n\t"
+ "stp x12, x13, [%[r], 32]\n\t"
+ "stp x14, x15, [%[r], 48]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
+ : "memory", "x4", "x5", "x6", "x7", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15"
+ );
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+static void sp_256_sqr_4(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "ldp x16, x17, [%[a], 0]\n\t"
+ "# A[0] * A[1]\n\t"
+ "mul x9, x16, x17\n\t"
+ "ldr x19, [%[a], 16]\n\t"
+ "umulh x10, x16, x17\n\t"
+ "ldr x20, [%[a], 24]\n\t"
+ "# A[0] * A[2]\n\t"
+ "mul x4, x16, x19\n\t"
+ "umulh x5, x16, x19\n\t"
+ "adds x10, x10, x4\n\t"
+ "# A[0] * A[3]\n\t"
+ "mul x4, x16, x20\n\t"
+ "adc x11, xzr, x5\n\t"
+ "umulh x5, x16, x20\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[1] * A[2]\n\t"
+ "mul x4, x17, x19\n\t"
+ "adc x12, xzr, x5\n\t"
+ "umulh x5, x17, x19\n\t"
+ "adds x11, x11, x4\n\t"
+ "# A[1] * A[3]\n\t"
+ "mul x4, x17, x20\n\t"
+ "adcs x12, x12, x5\n\t"
+ "umulh x5, x17, x20\n\t"
+ "adc x13, xzr, xzr\n\t"
+ "adds x12, x12, x4\n\t"
+ "# A[2] * A[3]\n\t"
+ "mul x4, x19, x20\n\t"
+ "adc x13, x13, x5\n\t"
+ "umulh x5, x19, x20\n\t"
+ "adds x13, x13, x4\n\t"
+ "adc x14, xzr, x5\n\t"
+ "# Double\n\t"
+ "adds x9, x9, x9\n\t"
+ "adcs x10, x10, x10\n\t"
+ "adcs x11, x11, x11\n\t"
+ "adcs x12, x12, x12\n\t"
+ "adcs x13, x13, x13\n\t"
+ "# A[0] * A[0]\n\t"
+ "mul x8, x16, x16\n\t"
+ "adcs x14, x14, x14\n\t"
+ "umulh x3, x16, x16\n\t"
+ "cset x15, cs\n\t"
+ "# A[1] * A[1]\n\t"
+ "mul x4, x17, x17\n\t"
+ "adds x9, x9, x3\n\t"
+ "umulh x5, x17, x17\n\t"
+ "adcs x10, x10, x4\n\t"
+ "# A[2] * A[2]\n\t"
+ "mul x6, x19, x19\n\t"
+ "adcs x11, x11, x5\n\t"
+ "umulh x7, x19, x19\n\t"
+ "adcs x12, x12, x6\n\t"
+ "# A[3] * A[3]\n\t"
+ "mul x16, x20, x20\n\t"
+ "adcs x13, x13, x7\n\t"
+ "umulh x17, x20, x20\n\t"
+ "adcs x14, x14, x16\n\t"
+ "adc x15, x15, x17\n\t"
+ "stp x8, x9, [%[r], 0]\n\t"
+ "stp x10, x11, [%[r], 16]\n\t"
+ "stp x12, x13, [%[r], 32]\n\t"
+ "stp x14, x15, [%[r], 48]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20"
+ );
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "ldp x3, x4, [%[a], 0]\n\t"
+ "ldp x7, x8, [%[b], 0]\n\t"
+ "adds x3, x3, x7\n\t"
+ "ldp x5, x6, [%[a], 16]\n\t"
+ "adcs x4, x4, x8\n\t"
+ "ldp x9, x10, [%[b], 16]\n\t"
+ "adcs x5, x5, x9\n\t"
+ "stp x3, x4, [%[r], 0]\n\t"
+ "adcs x6, x6, x10\n\t"
+ "stp x5, x6, [%[r], 16]\n\t"
+ "cset %[r], cs\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
+ );
+
+ return (sp_digit)r;
+}
+
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ __asm__ __volatile__ (
+ "ldp x3, x4, [%[a], 0]\n\t"
+ "ldp x7, x8, [%[b], 0]\n\t"
+ "subs x3, x3, x7\n\t"
+ "ldp x5, x6, [%[a], 16]\n\t"
+ "sbcs x4, x4, x8\n\t"
+ "ldp x9, x10, [%[b], 16]\n\t"
+ "sbcs x5, x5, x9\n\t"
+ "stp x3, x4, [%[r], 0]\n\t"
+ "sbcs x6, x6, x10\n\t"
+ "stp x5, x6, [%[r], 16]\n\t"
+ "csetm %[r], cc\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
+ );
+
+ return (sp_digit)r;
+}
+
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp,
+ sp_point_256** p)
{
int ret = MP_OKAY;
(void)heap;
@@ -18944,6 +19960,12 @@ static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p)
#endif
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -18956,7 +19978,7 @@ static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap)
}
#else
/* Clear point data if requested. */
- if (clear != 0) {
+ if ((p != NULL) && (clear != 0)) {
XMEMSET(p, 0, sizeof(*p));
}
#endif
@@ -19047,7 +20069,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -19081,7 +20104,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -19117,7 +20142,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
* p Point of type sp_point_256 (result).
* pm Point of type ecc_point.
*/
-static void sp_256_point_from_ecc_point_4(sp_point_256* p, const ecc_point* pm)
+static void sp_256_point_from_ecc_point_4(sp_point_256* p,
+ const ecc_point* pm)
{
XMEMSET(p->x, 0, sizeof(p->x));
XMEMSET(p->y, 0, sizeof(p->y));
@@ -19144,17 +20170,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = 4;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 4; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -19167,14 +20195,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 4; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -19609,7 +20639,7 @@ static void sp_256_mont_sqr_n_4(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint64_t p256_mod_minus_2[4] = {
@@ -19803,35 +20833,6 @@ static sp_digit sp_256_cond_sub_4(sp_digit* r, const sp_digit* a, const sp_digit
return (sp_digit)r;
}
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- __asm__ __volatile__ (
- "ldp x3, x4, [%[a], 0]\n\t"
- "ldp x7, x8, [%[b], 0]\n\t"
- "subs x3, x3, x7\n\t"
- "ldp x5, x6, [%[a], 16]\n\t"
- "sbcs x4, x4, x8\n\t"
- "ldp x9, x10, [%[b], 16]\n\t"
- "sbcs x5, x5, x9\n\t"
- "stp x3, x4, [%[r], 0]\n\t"
- "sbcs x6, x6, x10\n\t"
- "stp x5, x6, [%[r], 16]\n\t"
- "csetm %[r], cc\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
- );
-
- return (sp_digit)r;
-}
-
#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4
/* Reduce the number back to 256 bits using Montgomery reduction.
@@ -19996,7 +20997,8 @@ SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m,
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_4(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*4;
@@ -20514,7 +21516,8 @@ static void sp_256_mont_dbl_sub_4(sp_digit* r, const sp_digit* a, const sp_digit
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*4;
@@ -20812,8 +21815,8 @@ static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_4(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -20906,8 +21909,8 @@ static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, cons
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* p,
- int n, int m, sp_digit* t)
+static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r,
+ const sp_point_256* p, int n, int m, sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*4;
@@ -20918,6 +21921,7 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256*
sp_digit* y = r[(1< .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit qx_px[2 * 16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ qx_px = td + 8 * 16 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+
+ sp_1024_mont_add_16(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_16(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_16(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* h = t + 8 * 16;
+ sp_digit* r = t + 10 * 16;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_16(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_16(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_16(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_16(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_16(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_16(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_16(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_16(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_16(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_16(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_16(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_16(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_16(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_16(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_16(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_16(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_16(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_16(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_16(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_16(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 16;
+ sp_digit* pz2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* l = t + 8 * 16;
+ sp_digit* ty = t + 10 * 16;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_16(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_16(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_16(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_16(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_16(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_16(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_16(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_16(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_16(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_16(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_16(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* t2 = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_16(l, py, p1024_mod);
+ sp_1024_mont_inv_16(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_16(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_16(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_16(t2, t1, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_16(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_16(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_16(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* c = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_16(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_16(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_16(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_16(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_16(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_16(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_16(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_16(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_16(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 16;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_16(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_16(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_16(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_16(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 16 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_16(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_16(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_16(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_16(c, c, t);
+ sp_1024_mont_map_16(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_16(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_16(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_16(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_16(c, c, neg, t);
+ sp_1024_mont_map_16(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_16(c, c, t);
+ sp_1024_mont_map_16(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(neg, 1, NULL);
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_16(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j;
+ byte* d;
+
+ for (i = n - 1,j = 0; i >= 7; i -= 8) {
+ r[j] = ((sp_digit)a[i - 0] << 0) |
+ ((sp_digit)a[i - 1] << 8) |
+ ((sp_digit)a[i - 2] << 16) |
+ ((sp_digit)a[i - 3] << 24) |
+ ((sp_digit)a[i - 4] << 32) |
+ ((sp_digit)a[i - 5] << 40) |
+ ((sp_digit)a[i - 6] << 48) |
+ ((sp_digit)a[i - 7] << 56);
+ j++;
+ }
+
+ if (i >= 0) {
+ r[j] = 0;
+
+ d = (byte*)r;
+ switch (i) {
+ case 6: d[n - 1 - 6] = a[6]; //fallthrough
+ case 5: d[n - 1 - 5] = a[5]; //fallthrough
+ case 4: d[n - 1 - 4] = a[4]; //fallthrough
+ case 3: d[n - 1 - 3] = a[3]; //fallthrough
+ case 2: d[n - 1 - 2] = a[2]; //fallthrough
+ case 1: d[n - 1 - 1] = a[1]; //fallthrough
+ case 0: d[n - 1 - 0] = a[0]; //fallthrough
+ }
+ j++;
+ }
+
+ for (; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_16(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*16];
+ sp_digit t2d[2*16];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int64_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 16;
+ t2 = d + 2 * 16;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_16(t1, point->y);
+ (void)sp_1024_mod_16(t1, t1, p1024_mod);
+ sp_1024_sqr_16(t2, point->x);
+ (void)sp_1024_mod_16(t2, t2, p1024_mod);
+ sp_1024_mul_16(t2, t2, point->x);
+ (void)sp_1024_mod_16(t2, t2, p1024_mod);
+ (void)sp_1024_sub_16(t2, p1024_mod, t2);
+ sp_1024_mont_add_16(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_16(t1, p1024_mod);
+ sp_1024_cond_sub_16(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_16(t1);
+ if (!sp_1024_iszero_16(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_16(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 16, pX);
+ sp_1024_from_mp(pub->y, 16, pY);
+ sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_16(pub, NULL);
+ }
+
+ sp_1024_point_free_16(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[16];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_16(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 16, pX);
+ sp_1024_from_mp(pub->y, 16, pY);
+ sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 16, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_16(pub->x) != 0) &&
+ (sp_1024_iszero_16(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_16(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_16(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_16(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_16(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_16(p->x) == 0) ||
+ (sp_1024_iszero_16(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_16(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_16(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_16(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_16(p, 0, heap);
+ sp_1024_point_free_16(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_SP_ARM64_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c
index 42c44ad7c..a7e2ddd70 100644
--- a/wolfcrypt/src/sp_armthumb.c
+++ b/wolfcrypt/src/sp_armthumb.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -58,7 +58,8 @@
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -100,7 +101,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -134,7 +136,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -173,7 +177,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 2048 / 8 - 1;
a[j] = 0;
@@ -716,7 +723,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
sp_digit a1[8];
sp_digit b1[8];
sp_digit z2[16];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_8(a1, a, &a[8]);
cb = sp_2048_add_8(b1, b, &b[8]);
@@ -1105,7 +1114,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
sp_digit a1[16];
sp_digit b1[16];
sp_digit z2[32];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_16(a1, a, &a[16]);
cb = sp_2048_add_16(b1, b, &b[16]);
@@ -1763,7 +1774,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
sp_digit a1[32];
sp_digit b1[32];
sp_digit z2[64];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_32(a1, a, &a[32]);
cb = sp_2048_add_32(b1, b, &b[32]);
@@ -2498,7 +2511,7 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -2507,7 +2520,8 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -2516,7 +2530,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -2791,8 +2805,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_32(r, a, b);
sp_2048_mont_reduce_32(r, m, mp);
@@ -2805,8 +2819,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_32(r, a);
sp_2048_mont_reduce_32(r, m, mp);
@@ -3140,7 +3154,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3206,34 +3221,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -3285,7 +3300,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3367,34 +3383,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -3425,7 +3441,7 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -3442,7 +3458,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m)
sp_2048_sub_in_place_64(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -3634,8 +3650,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_64(r, a, b);
sp_2048_mont_reduce_64(r, m, mp);
@@ -3648,8 +3664,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_64(r, a);
sp_2048_mont_reduce_64(r, m, mp);
@@ -4000,7 +4016,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4066,34 +4083,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -4145,7 +4162,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4227,34 +4245,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -4299,11 +4317,13 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[128], m[64], r[128];
+ sp_digit a[128];
+ sp_digit m[64];
+ sp_digit r[128];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -4479,9 +4499,9 @@ SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -4545,8 +4565,11 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[64 * 2];
- sp_digit p[32], q[32], dp[32];
- sp_digit tmpa[64], tmpb[64];
+ sp_digit p[32];
+ sp_digit q[32];
+ sp_digit dp[32];
+ sp_digit tmpa[64];
+ sp_digit tmpb[64];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -4643,7 +4666,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -4666,17 +4689,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 64;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -4689,14 +4714,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -4723,10 +4750,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5185,10 +5215,12 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5223,34 +5255,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_2048_lshift_64(r, norm, (byte)y);
+ sp_2048_lshift_64(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -5261,7 +5293,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_2048_mont_sqr_64(r, r, m, mp);
sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_lshift_64(r, r, (byte)y);
+ sp_2048_lshift_64(r, r, y);
sp_2048_mul_d_64(tmp, norm, r[64]);
r[64] = 0;
o = sp_2048_add_64(r, r, tmp);
@@ -5297,11 +5329,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
word32 i;
@@ -5336,6 +5370,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -5357,10 +5392,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5397,7 +5435,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -5411,7 +5449,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -5453,7 +5492,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -5487,7 +5527,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -5526,7 +5568,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 3072 / 8 - 1;
a[j] = 0;
@@ -6153,7 +6198,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
sp_digit a1[12];
sp_digit b1[12];
sp_digit z2[24];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_12(a1, a, &a[12]);
cb = sp_3072_add_12(b1, b, &b[12]);
@@ -6683,7 +6730,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
sp_digit a1[24];
sp_digit b1[24];
sp_digit z2[48];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_24(a1, a, &a[24]);
cb = sp_3072_add_24(b1, b, &b[24]);
@@ -7608,7 +7657,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
sp_digit a1[48];
sp_digit b1[48];
sp_digit z2[96];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_48(a1, a, &a[48]);
cb = sp_3072_add_48(b1, b, &b[48]);
@@ -8359,7 +8410,7 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -8368,7 +8419,8 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -8377,7 +8429,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -8653,8 +8705,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_48(r, a, b);
sp_3072_mont_reduce_48(r, m, mp);
@@ -8667,8 +8719,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_48(r, a);
sp_3072_mont_reduce_48(r, m, mp);
@@ -9002,7 +9054,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -9068,34 +9121,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -9147,7 +9200,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -9229,34 +9283,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -9287,7 +9341,7 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -9304,7 +9358,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m)
sp_3072_sub_in_place_96(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -9500,8 +9554,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_96(r, a, b);
sp_3072_mont_reduce_96(r, m, mp);
@@ -9514,8 +9568,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_96(r, a);
sp_3072_mont_reduce_96(r, m, mp);
@@ -9868,7 +9922,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -9934,34 +9989,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -10013,7 +10068,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10095,34 +10151,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -10167,11 +10223,13 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[192], m[96], r[192];
+ sp_digit a[192];
+ sp_digit m[96];
+ sp_digit r[192];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -10347,9 +10405,9 @@ SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -10413,8 +10471,11 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[96 * 2];
- sp_digit p[48], q[48], dp[48];
- sp_digit tmpa[96], tmpb[96];
+ sp_digit p[48];
+ sp_digit q[48];
+ sp_digit dp[48];
+ sp_digit tmpa[96];
+ sp_digit tmpb[96];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -10511,7 +10572,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -10534,17 +10595,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 96;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -10557,14 +10620,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -10591,10 +10656,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -11251,10 +11319,12 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11289,34 +11359,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_3072_lshift_96(r, norm, (byte)y);
+ sp_3072_lshift_96(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -11327,7 +11397,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_3072_mont_sqr_96(r, r, m, mp);
sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_lshift_96(r, r, (byte)y);
+ sp_3072_lshift_96(r, r, y);
sp_3072_mul_d_96(tmp, norm, r[96]);
r[96] = 0;
o = sp_3072_add_96(r, r, tmp);
@@ -11363,11 +11433,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
word32 i;
@@ -11402,6 +11474,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -11423,10 +11496,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -11463,7 +11539,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -11477,7 +11553,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -11519,7 +11596,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -11553,7 +11631,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -11592,7 +11672,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 4096 / 8 - 1;
a[j] = 0;
@@ -12738,7 +12821,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
sp_digit a1[64];
sp_digit b1[64];
sp_digit z2[128];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_64(a1, a, &a[64]);
cb = sp_2048_add_64(b1, b, &b[64]);
@@ -13137,7 +13222,8 @@ SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -13146,7 +13232,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -13232,7 +13318,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m)
sp_4096_sub_in_place_128(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -13426,8 +13512,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_128(r, a, b);
sp_4096_mont_reduce_128(r, m, mp);
@@ -13440,8 +13526,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_128(r, a);
sp_4096_mont_reduce_128(r, m, mp);
@@ -13794,7 +13880,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -13860,34 +13947,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -13939,7 +14026,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -14021,34 +14109,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -14093,11 +14181,13 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[256], m[128], r[256];
+ sp_digit a[256];
+ sp_digit m[128];
+ sp_digit r[256];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -14274,9 +14364,9 @@ SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -14340,8 +14430,11 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[128 * 2];
- sp_digit p[64], q[64], dp[64];
- sp_digit tmpa[128], tmpb[128];
+ sp_digit p[64];
+ sp_digit q[64];
+ sp_digit dp[64];
+ sp_digit tmpa[128];
+ sp_digit tmpb[128];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -14438,7 +14531,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -14461,17 +14554,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 128;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -14484,14 +14579,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -14518,10 +14615,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -15374,10 +15474,12 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -15412,34 +15514,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_4096_lshift_128(r, norm, (byte)y);
+ sp_4096_lshift_128(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -15450,7 +15552,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_4096_mont_sqr_128(r, r, m, mp);
sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_lshift_128(r, r, (byte)y);
+ sp_4096_lshift_128(r, r, y);
sp_4096_mul_d_128(tmp, norm, r[128]);
r[128] = 0;
o = sp_4096_add_128(r, r, tmp);
@@ -15486,11 +15588,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
word32 i;
@@ -15525,6 +15629,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -15537,19 +15642,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 8];
+ /* Y ordinate of point. */
sp_digit y[2 * 8];
+ /* Z ordinate of point. */
sp_digit z[2 * 8];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -15619,305 +15728,6 @@ static const sp_digit p256_b[8] = {
};
#endif
-static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p))
-#endif
-
-
-static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- */
-static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
- int64_t t[8];
- int64_t a64[8];
- int64_t o;
-
- (void)m;
-
- a64[0] = a[0];
- a64[1] = a[1];
- a64[2] = a[2];
- a64[3] = a[3];
- a64[4] = a[4];
- a64[5] = a[5];
- a64[6] = a[6];
- a64[7] = a[7];
-
- /* 1 1 0 -1 -1 -1 -1 0 */
- t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6];
- /* 0 1 1 0 -1 -1 -1 -1 */
- t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7];
- /* 0 0 1 1 0 -1 -1 -1 */
- t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7];
- /* -1 -1 0 2 2 1 0 -1 */
- t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7];
- /* 0 -1 -1 0 2 2 1 0 */
- t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6];
- /* 0 0 -1 -1 0 2 2 1 */
- t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7];
- /* -1 -1 0 0 0 1 3 2 */
- t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7];
- /* 1 0 -1 -1 -1 -1 0 3 */
- t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7];
-
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- o = t[7] >> 32; t[7] &= 0xffffffff;
- t[0] += o;
- t[3] -= o;
- t[6] -= o;
- t[7] += o;
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- r[0] = t[0];
- r[1] = t[1];
- r[2] = t[2];
- r[3] = t[3];
- r[4] = t[4];
- r[5] = t[5];
- r[6] = t[6];
- r[7] = t[7];
-
- return MP_OKAY;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 32
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_256.
- *
- * p Point of type sp_point_256 (result).
- * pm Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_256_from_mp(p->x, 8, pm->x);
- sp_256_from_mp(p->y, 8, pm->y);
- sp_256_from_mp(p->z, 8, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_256_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 8);
- r->used = 8;
- mp_clamp(r);
-#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 8; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 32 - s;
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 8; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_256 to type ecc_point.
- *
- * p Point of type sp_point_256.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_8(const sp_point_256* p, ecc_point* pm)
-{
- int err;
-
- err = sp_256_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -16018,6 +15828,660 @@ SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a,
XMEMCPY(r, tmp, sizeof(tmp));
}
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r6, #64\n\t"
+ "neg r6, r6\n\t"
+ "add sp, r6\n\t"
+ "mov r10, sp\n\t"
+ "mov r9, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #28\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov r2, r8\n\t"
+ "sub r2, %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add r2, r9\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+ "beq 4f\n\t"
+ "# Multiply * 2: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply * 2: Done\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "# Square: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r6\n\t"
+ "add r3, r6\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "mul r7, r7\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #15\n\t"
+ "lsl r6, r6, #17\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Square: Done\n\t"
+ "\n5:\n\t"
+ "add %[a], #4\n\t"
+ "sub r2, #4\n\t"
+ "mov r6, #32\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "beq 3f\n\t"
+ "cmp %[a], r2\n\t"
+ "bgt 3f\n\t"
+ "mov r7, r8\n\t"
+ "add r7, r9\n\t"
+ "cmp %[a], r7\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r10\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #56\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "mov %[a], r9\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[r], r11\n\t"
+ "mov %[a], r10\n\t"
+ "mov r3, #60\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "sub r3, #4\n\t"
+ "bge 4b\n\t"
+ "mov r6, #64\n\t"
+ "add sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
+ );
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r7, #0\n\t"
+ "add r6, #32\n\t"
+ "sub r7, #1\n\t"
+ "\n1:\n\t"
+ "add %[c], r7\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "add r4, r5\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #4]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #12]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #20]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #28]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #28]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, #32\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "sbc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp,
+ sp_point_256** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ */
+static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ int64_t t[8];
+ int64_t a64[8];
+ int64_t o;
+
+ (void)m;
+
+ a64[0] = a[0];
+ a64[1] = a[1];
+ a64[2] = a[2];
+ a64[3] = a[3];
+ a64[4] = a[4];
+ a64[5] = a[5];
+ a64[6] = a[6];
+ a64[7] = a[7];
+
+ /* 1 1 0 -1 -1 -1 -1 0 */
+ t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6];
+ /* 0 1 1 0 -1 -1 -1 -1 */
+ t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7];
+ /* 0 0 1 1 0 -1 -1 -1 */
+ t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7];
+ /* -1 -1 0 2 2 1 0 -1 */
+ t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7];
+ /* 0 -1 -1 0 2 2 1 0 */
+ t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6];
+ /* 0 0 -1 -1 0 2 2 1 */
+ t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7];
+ /* -1 -1 0 0 0 1 3 2 */
+ t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7];
+ /* 1 0 -1 -1 -1 -1 0 3 */
+ t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7];
+
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ o = t[7] >> 32; t[7] &= 0xffffffff;
+ t[0] += o;
+ t[3] -= o;
+ t[6] -= o;
+ t[7] += o;
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+ r[3] = t[3];
+ r[4] = t[4];
+ r[5] = t[5];
+ r[6] = t[6];
+ r[7] = t[7];
+
+ return MP_OKAY;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_256.
+ *
+ * p Point of type sp_point_256 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_256_point_from_ecc_point_8(sp_point_256* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_256_from_mp(p->x, 8, pm->x);
+ sp_256_from_mp(p->y, 8, pm->y);
+ sp_256_from_mp(p->z, 8, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_256_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 8);
+ r->used = 8;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 8; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 8; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_256 to type ecc_point.
+ *
+ * p Point of type sp_point_256.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_256_point_to_ecc_point_8(const sp_point_256* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_256_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -16332,161 +16796,13 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_256_mul_8(r, a, b);
sp_256_mont_reduce_8(r, m, mp);
}
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #64\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #28\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #32\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #56\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #60\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #64\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
-}
-
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -16494,8 +16810,8 @@ SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_256_sqr_8(r, a);
sp_256_mont_reduce_8(r, m, mp);
@@ -16519,7 +16835,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint32_t p256_mod_minus_2[8] = {
@@ -16652,7 +16968,8 @@ SP_NOINLINE static int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_8(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*8;
@@ -16688,100 +17005,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "add r6, #32\n\t"
- "sub r7, #1\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -17415,97 +17638,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d
sp_256_mont_sub_8(y, y, t2, p256_mod);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "add r6, #32\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "sbc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[b], #0]\n\t"
- "ldr r7, [%[b], #4]\n\t"
- "sub r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[a], #12]\n\t"
- "ldr r6, [%[b], #8]\n\t"
- "ldr r7, [%[b], #12]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r5, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[b], #16]\n\t"
- "ldr r7, [%[b], #20]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[a], #28]\n\t"
- "ldr r6, [%[b], #24]\n\t"
- "ldr r7, [%[b], #28]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r5, [%[r], #28]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Compare two numbers to determine if they are equal.
* Constant time implementation.
*
@@ -17729,8 +17861,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_8(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -17885,9 +18017,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 256 doubles.
+ * 76 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -17916,7 +18050,8 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -17989,7 +18124,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
i = 6;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_256_get_point_16_8(rt, t, y);
@@ -18054,12 +18189,6 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_256 {
- sp_digit x[8];
- sp_digit y[8];
-} sp_table_entry_256;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -18068,7 +18197,8 @@ typedef struct sp_table_entry_256 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*8;
@@ -18149,6 +18279,36 @@ static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t)
sp_256_div2_8(y, y, p256_mod);
}
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 8;
+ sp_digit* tmp = t + 4 * 8;
+
+ sp_256_mont_inv_8(t1, a->z, tmp);
+
+ sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
+ sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
+
+ sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
+ sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
+ XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
+}
+
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_256 {
+ sp_digit x[8];
+ sp_digit y[8];
+} sp_table_entry_256;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -18234,29 +18394,11 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a Point to convert.
- * t Temporary data.
- */
-static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
-{
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2 * 8;
- sp_digit* tmp = t + 4 * 8;
-
- sp_256_mont_inv_8(t1, a->z, tmp);
-
- sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
-
- sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
- XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 64 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -18267,12 +18409,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -18391,8 +18536,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -18414,8 +18561,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -18443,8 +18592,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=63; j<4; j++,x+=64) {
+ x = 63;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -18458,8 +18609,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=62; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=64) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -18501,16 +18654,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -18518,9 +18680,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -18629,6 +18797,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 32 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -18639,12 +18811,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -18763,8 +18938,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -18786,8 +18963,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -18815,8 +18994,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=31; j<8; j++,x+=32) {
+ x = 31;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -18830,8 +19011,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=30; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=32) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -18873,16 +19056,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -18890,9 +19082,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -19009,8 +19207,8 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -19051,7 +19249,94 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(point, gm);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 64 between points.
+ */
static const sp_table_entry_256 p256_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -19136,6 +19421,11 @@ static const sp_table_entry_256 p256_table[16] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -19151,6 +19441,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 32 between points.
+ */
static const sp_table_entry_256 p256_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -20435,6 +20729,11 @@ static const sp_table_entry_256 p256_table[256] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -20460,7 +20759,7 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -20501,6 +20800,87 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P256 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -20514,7 +20894,7 @@ static int sp_256_iszero_8(const sp_digit* a)
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -20563,7 +20943,8 @@ SP_NOINLINE static void sp_256_add_one_8(sp_digit* a)
*/
static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -20707,7 +21088,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_256_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 256 / 8 - 1;
a[j] = 0;
@@ -20748,7 +21132,7 @@ static void sp_256_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -21190,7 +21574,7 @@ static const uint32_t p256_order_minus_2[8] = {
};
#else
/* The low half of the order-2 of the P256 curve. */
-static const uint32_t p256_order_low[4] = {
+static const sp_int_digit p256_order_low[4] = {
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
};
#endif /* WOLFSSL_SP_SMALL */
@@ -21336,7 +21720,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6 */
for (i=127; i>=112; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21346,7 +21730,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
for (i=107; i>=64; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21356,7 +21740,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
for (i=59; i>=32; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21366,7 +21750,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
for (i=27; i>=0; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21377,12 +21761,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_256_mul_8(k, k, p256_norm_order);
+ err = sp_256_mod_8(k, k, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(k);
+
+ /* kInv = 1/k mod order */
+ sp_256_mont_inv_order_8(kInv, k, tmp);
+ sp_256_norm_8(kInv);
+
+ /* s = r * x + e */
+ sp_256_mul_8(x, x, r);
+ err = sp_256_mod_8(x, x, p256_order);
+ }
+ if (err == MP_OKAY) {
+ sp_256_norm_8(x);
+ carry = sp_256_add_8(s, e, x);
+ sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
+ sp_256_norm_8(s);
+ c = sp_256_cmp_8(s, p256_order);
+ sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
+ sp_256_norm_8(s);
+
+ /* s = s * k^-1 mod order */
+ sp_256_mont_mul_order_8(s, s, kInv);
+ sp_256_norm_8(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 256 bits] from binary
* r = (k.G)->x mod order
@@ -21417,8 +21852,8 @@ typedef struct sp_ecc_sign_256_ctx {
int i;
} sp_ecc_sign_256_ctx;
-int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
@@ -21558,8 +21993,8 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -21577,11 +22012,9 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_256* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -21612,7 +22045,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 32U) {
hashLen = 32U;
@@ -21620,8 +22052,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_256_from_mp(x, 8, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
@@ -21631,7 +22061,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL);
+ err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -21642,38 +22072,15 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0));
sp_256_norm_8(r);
- /* Conv k to Montgomery form (mod order) */
- sp_256_mul_8(k, k, p256_norm_order);
- err = sp_256_mod_8(k, k, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(k);
- /* kInv = 1/k mod order */
- sp_256_mont_inv_order_8(kInv, k, tmp);
- sp_256_norm_8(kInv);
-
- /* s = r * x + e */
- sp_256_mul_8(x, x, r);
- err = sp_256_mod_8(x, x, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(x);
+ sp_256_from_mp(x, 8, priv);
sp_256_from_bin(e, 8, hash, (int)hashLen);
- carry = sp_256_add_8(s, e, x);
- sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
- sp_256_norm_8(s);
- c = sp_256_cmp_8(s, p256_order);
- sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
- sp_256_norm_8(s);
- /* s = s * k^-1 mod order */
- sp_256_mont_mul_order_8(s, s, kInv);
- sp_256_norm_8(s);
+ err = sp_256_calc_s_8(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_256_iszero_8(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -21701,7 +22108,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U);
#endif
sp_256_point_free_8(point, 1, heap);
@@ -22286,6 +22692,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2,
+ sp_digit* tmp)
+{
+
+ sp_256_proj_point_add_8(p1, p1, p2, tmp);
+ if (sp_256_iszero_8(p1->z)) {
+ if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
+ sp_256_proj_point_dbl_8(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_256_mod_inv_8(s, s, p256_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_256_mul_8(s, s, p256_norm_order);
+ }
+ err = sp_256_mod_8(s, s, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_256_mont_inv_order_8(s, s, tmp);
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#else
+ {
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_256_add_points_8(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 256)
@@ -22304,8 +22800,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_256_ctx {
@@ -22324,8 +22819,9 @@ typedef struct sp_ecc_verify_256_ctx {
sp_point_256 p2;
} sp_ecc_verify_256_ctx;
-int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
@@ -22479,8 +22975,9 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -22499,7 +22996,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_256* p1;
sp_point_256* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_256_point_new_8(heap, p1d, p1);
@@ -22540,66 +23037,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_256_mod_inv_8(s, s, p256_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_256_mul_8(s, s, p256_norm_order);
- }
- err = sp_256_mod_8(s, s, p256_order);
+ err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_256_norm_8(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_256_mont_inv_order_8(s, s, tmp);
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#else
- {
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_256_proj_point_add_8(p1, p1, p2, tmp);
- if (sp_256_iszero_8(p1->z)) {
- if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
- sp_256_proj_point_dbl_8(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_256_from_mp(u2, 8, r);
@@ -22621,16 +23061,16 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_256_cmp_8(u2, p256_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
- p256_mp_mod);
- *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
+ p256_mp_mod);
+ *res = (sp_256_cmp_8(p1->x, u1) == 0);
}
}
}
@@ -22654,7 +23094,8 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
+static int sp_256_ecc_is_point_8(const sp_point_256* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -22717,7 +23158,7 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 pubd;
@@ -22751,7 +23192,8 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[8];
@@ -22805,12 +23247,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_256_cmp_8(pub->x, p256_mod) >= 0 ||
- sp_256_cmp_8(pub->y, p256_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(pub->x, p256_mod) >= 0) ||
+ (sp_256_cmp_8(pub->y, p256_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -22822,12 +23263,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_256_iszero_8(p->x) == 0) ||
- (sp_256_iszero_8(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) ||
+ (sp_256_iszero_8(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -22835,12 +23274,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_256_cmp_8(p->x, pub->x) != 0 ||
- sp_256_cmp_8(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(p->x, pub->x) != 0) ||
+ (sp_256_cmp_8(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -23030,7 +23468,7 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_256_from_mp(p->y, 8, pY);
sp_256_from_mp(p->z, 8, pZ);
- sp_256_map_8(p, p, tmp);
+ sp_256_map_8(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -23210,9 +23648,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
/* Point structure to use. */
typedef struct sp_point_384 {
+ /* X ordinate of point. */
sp_digit x[2 * 12];
+ /* Y ordinate of point. */
sp_digit y[2 * 12];
+ /* Z ordinate of point. */
sp_digit z[2 * 12];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_384;
@@ -23282,336 +23724,6 @@ static const sp_digit p384_b[12] = {
};
#endif
-static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
-#endif
-
-
-static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- int64_t* t;
-#else
- int64_t t[12];
-#endif
- int64_t o;
- int err = MP_OKAY;
-
- (void)m;
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
- if (t == NULL) {
- err = MEMORY_E;
- }
-#endif
-
- if (err == MP_OKAY) {
- /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
- t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11];
- /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
- t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
- t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11];
- /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
- t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11];
- /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
- t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11];
- /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
- t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
- t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11];
- /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
- t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11];
- /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
- t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8];
- /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
- t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9];
- /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
- t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10];
- /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
- t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11];
-
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
- o = t[11] >> 32; t[11] &= 0xffffffff;
- t[0] += o;
- t[1] -= o;
- t[3] += o;
- t[4] += o;
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
-
- r[0] = t[0];
- r[1] = t[1];
- r[2] = t[2];
- r[3] = t[3];
- r[4] = t[4];
- r[5] = t[5];
- r[6] = t[6];
- r[7] = t[7];
- r[8] = t[8];
- r[9] = t[9];
- r[10] = t[10];
- r[11] = t[11];
- }
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- if (t != NULL)
- XFREE(t, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
- return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 32
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_384.
- *
- * p Point of type sp_point_384 (result).
- * pm Point of type ecc_point.
- */
-static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_384_from_mp(p->x, 12, pm->x);
- sp_384_from_mp(p->y, 12, pm->y);
- sp_384_from_mp(p->z, 12, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_384_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
- r->used = 12;
- mp_clamp(r);
-#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 32 - s;
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_384 to type ecc_point.
- *
- * p Point of type sp_point_384.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
-{
- int err;
-
- err = sp_384_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -23712,6 +23824,723 @@ SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a,
XMEMCPY(r, tmp, sizeof(tmp));
}
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r6, #96\n\t"
+ "neg r6, r6\n\t"
+ "add sp, r6\n\t"
+ "mov r10, sp\n\t"
+ "mov r9, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #44\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov r2, r8\n\t"
+ "sub r2, %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add r2, r9\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+ "beq 4f\n\t"
+ "# Multiply * 2: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply * 2: Done\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "# Square: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r6\n\t"
+ "add r3, r6\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "mul r7, r7\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #15\n\t"
+ "lsl r6, r6, #17\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Square: Done\n\t"
+ "\n5:\n\t"
+ "add %[a], #4\n\t"
+ "sub r2, #4\n\t"
+ "mov r6, #48\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "beq 3f\n\t"
+ "cmp %[a], r2\n\t"
+ "bgt 3f\n\t"
+ "mov r7, r8\n\t"
+ "add r7, r9\n\t"
+ "cmp %[a], r7\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r10\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #88\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "mov %[a], r9\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[r], r11\n\t"
+ "mov %[a], r10\n\t"
+ "mov r3, #92\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "sub r3, #4\n\t"
+ "bge 4b\n\t"
+ "mov r6, #96\n\t"
+ "add sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
+ );
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r7, #0\n\t"
+ "add r6, #48\n\t"
+ "sub r7, #1\n\t"
+ "\n1:\n\t"
+ "add %[c], r7\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "add r4, r5\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #4]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #12]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #20]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #28]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #36]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #44]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, #48\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "sbc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp,
+ sp_point_384** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ int64_t* t;
+#else
+ int64_t t[12];
+#endif
+ int64_t o;
+ int err = MP_OKAY;
+
+ (void)m;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+
+ if (err == MP_OKAY) {
+ /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
+ t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11];
+ /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
+ t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11];
+ /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
+ t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11];
+ /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
+ t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11];
+ /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
+ t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11];
+ /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
+ t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11];
+ /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
+ t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11];
+ /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
+ t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11];
+ /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
+ t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8];
+ /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
+ t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9];
+ /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
+ t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10];
+ /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
+ t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11];
+
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+ o = t[11] >> 32; t[11] &= 0xffffffff;
+ t[0] += o;
+ t[1] -= o;
+ t[3] += o;
+ t[4] += o;
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+ r[3] = t[3];
+ r[4] = t[4];
+ r[5] = t[5];
+ r[6] = t[6];
+ r[7] = t[7];
+ r[8] = t[8];
+ r[9] = t[9];
+ r[10] = t[10];
+ r[11] = t[11];
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL)
+ XFREE(t, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+ return err;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_384.
+ *
+ * p Point of type sp_point_384 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_384_point_from_ecc_point_12(sp_point_384* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_384_from_mp(p->x, 12, pm->x);
+ sp_384_from_mp(p->y, 12, pm->y);
+ sp_384_from_mp(p->z, 12, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_384_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
+ r->used = 12;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_384 to type ecc_point.
+ *
+ * p Point of type sp_point_384.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_384_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -23903,161 +24732,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_384_mul_12(r, a, b);
sp_384_mont_reduce_12(r, m, mp);
}
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #96\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #44\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #48\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #88\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #92\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #96\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
-}
-
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -24065,8 +24746,8 @@ SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_384_sqr_12(r, a);
sp_384_mont_reduce_12(r, m, mp);
@@ -24090,7 +24771,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P384 curve. */
static const uint32_t p384_mod_minus_2[12] = {
@@ -24239,7 +24920,8 @@ SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
+static void sp_384_map_12(sp_point_384* r, const sp_point_384* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*12;
@@ -24275,116 +24957,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "add r6, #48\n\t"
- "sub r7, #1\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -24431,113 +25003,6 @@ SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const
sp_384_cond_sub_12(r, r, m, 0 - o);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "add r6, #48\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "sbc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[b], #0]\n\t"
- "ldr r7, [%[b], #4]\n\t"
- "sub r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[a], #12]\n\t"
- "ldr r6, [%[b], #8]\n\t"
- "ldr r7, [%[b], #12]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r5, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[b], #16]\n\t"
- "ldr r7, [%[b], #20]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[a], #28]\n\t"
- "ldr r6, [%[b], #24]\n\t"
- "ldr r7, [%[b], #28]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r5, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[a], #36]\n\t"
- "ldr r6, [%[b], #32]\n\t"
- "ldr r7, [%[b], #36]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #32]\n\t"
- "str r5, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[a], #44]\n\t"
- "ldr r6, [%[b], #40]\n\t"
- "ldr r7, [%[b], #44]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #40]\n\t"
- "str r5, [%[r], #44]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -25094,8 +25559,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q,
- sp_digit* t)
+static void sp_384_proj_point_add_12(sp_point_384* r,
+ const sp_point_384* p, const sp_point_384* q, sp_digit* t)
{
const sp_point_384* ap[2];
sp_point_384* rp[2];
@@ -25274,9 +25739,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 384 doubles.
+ * 108 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -25305,7 +25772,8 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -25378,7 +25846,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
i = 10;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_384_get_point_16_12(rt, t, y);
@@ -25443,12 +25911,6 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_384 {
- sp_digit x[12];
- sp_digit y[12];
-} sp_table_entry_384;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -25457,7 +25919,8 @@ typedef struct sp_table_entry_384 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t)
+static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*12;
@@ -25538,6 +26001,36 @@ static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t)
sp_384_div2_12(y, y, p384_mod);
}
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 12;
+ sp_digit* tmp = t + 4 * 12;
+
+ sp_384_mont_inv_12(t1, a->z, tmp);
+
+ sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
+ sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
+
+ sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod);
+ sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod);
+ XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
+}
+
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_384 {
+ sp_digit x[12];
+ sp_digit y[12];
+} sp_table_entry_384;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -25623,29 +26116,11 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a Point to convert.
- * t Temporary data.
- */
-static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
-{
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2 * 12;
- sp_digit* tmp = t + 4 * 12;
-
- sp_384_mont_inv_12(t1, a->z, tmp);
-
- sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
- sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
-
- sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod);
- sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod);
- XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
-}
-
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 96 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -25656,12 +26131,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -25796,8 +26274,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -25819,8 +26299,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -25848,8 +26330,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=95; j<4; j++,x+=96) {
+ x = 95;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -25863,8 +26347,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=94; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=96) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -25906,16 +26392,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -25923,9 +26418,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -26034,6 +26535,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 48 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -26044,12 +26549,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -26184,8 +26692,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -26207,8 +26717,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -26236,8 +26748,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=47; j<8; j++,x+=48) {
+ x = 47;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -26251,8 +26765,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=46; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=48) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -26294,16 +26810,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -26311,9 +26836,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -26430,8 +26961,8 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -26472,7 +27003,94 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(point, gm);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 96 between points.
+ */
static const sp_table_entry_384 p384_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -26557,6 +27175,11 @@ static const sp_table_entry_384 p384_table[16] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -26572,6 +27195,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 48 between points.
+ */
static const sp_table_entry_384 p384_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -27856,6 +28483,11 @@ static const sp_table_entry_384 p384_table[256] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -27881,7 +28513,7 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -27922,6 +28554,87 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P384 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -27936,7 +28649,7 @@ static int sp_384_iszero_12(const sp_digit* a)
a[8] | a[9] | a[10] | a[11]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -27997,7 +28710,8 @@ SP_NOINLINE static void sp_384_add_one_12(sp_digit* a)
*/
static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -28141,7 +28855,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_384_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 384 / 8 - 1;
a[j] = 0;
@@ -28182,7 +28899,7 @@ static void sp_384_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -28646,7 +29363,6 @@ static const uint32_t p384_order_minus_2[12] = {
/* The low half of the order-2 of the P384 curve. */
static const uint32_t p384_order_low[6] = {
0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
-
};
#endif /* WOLFSSL_SP_SMALL */
@@ -28794,7 +29510,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
sp_384_mont_mul_order_12(t2, t2, t);
for (i=191; i>=1; i--) {
sp_384_mont_sqr_order_12(t2, t2);
- if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_384_mont_mul_order_12(t2, t2, a);
}
}
@@ -28803,12 +29519,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_384_mul_12(k, k, p384_norm_order);
+ err = sp_384_mod_12(k, k, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(k);
+
+ /* kInv = 1/k mod order */
+ sp_384_mont_inv_order_12(kInv, k, tmp);
+ sp_384_norm_12(kInv);
+
+ /* s = r * x + e */
+ sp_384_mul_12(x, x, r);
+ err = sp_384_mod_12(x, x, p384_order);
+ }
+ if (err == MP_OKAY) {
+ sp_384_norm_12(x);
+ carry = sp_384_add_12(s, e, x);
+ sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
+ sp_384_norm_12(s);
+ c = sp_384_cmp_12(s, p384_order);
+ sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
+ sp_384_norm_12(s);
+
+ /* s = s * k^-1 mod order */
+ sp_384_mont_mul_order_12(s, s, kInv);
+ sp_384_norm_12(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 384 bits] from binary
* r = (k.G)->x mod order
@@ -28843,8 +29610,8 @@ typedef struct sp_ecc_sign_384_ctx {
int i;
} sp_ecc_sign_384_ctx;
-int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
@@ -28984,8 +29751,8 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -29003,11 +29770,9 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_384* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -29038,7 +29803,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 48U) {
hashLen = 48U;
@@ -29046,8 +29810,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_384_from_mp(x, 12, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_384_ecc_gen_k_12(rng, k);
@@ -29057,7 +29819,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL);
+ err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -29068,38 +29830,15 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0));
sp_384_norm_12(r);
- /* Conv k to Montgomery form (mod order) */
- sp_384_mul_12(k, k, p384_norm_order);
- err = sp_384_mod_12(k, k, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(k);
- /* kInv = 1/k mod order */
- sp_384_mont_inv_order_12(kInv, k, tmp);
- sp_384_norm_12(kInv);
-
- /* s = r * x + e */
- sp_384_mul_12(x, x, r);
- err = sp_384_mod_12(x, x, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(x);
+ sp_384_from_mp(x, 12, priv);
sp_384_from_bin(e, 12, hash, (int)hashLen);
- carry = sp_384_add_12(s, e, x);
- sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
- sp_384_norm_12(s);
- c = sp_384_cmp_12(s, p384_order);
- sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
- sp_384_norm_12(s);
- /* s = s * k^-1 mod order */
- sp_384_mont_mul_order_12(s, s, kInv);
- sp_384_norm_12(s);
+ err = sp_384_calc_s_12(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_384_iszero_12(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -29127,7 +29866,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U);
#endif
sp_384_point_free_12(point, 1, heap);
@@ -29919,6 +30657,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2,
+ sp_digit* tmp)
+{
+
+ sp_384_proj_point_add_12(p1, p1, p2, tmp);
+ if (sp_384_iszero_12(p1->z)) {
+ if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
+ sp_384_proj_point_dbl_12(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ p1->x[8] = 0;
+ p1->x[9] = 0;
+ p1->x[10] = 0;
+ p1->x[11] = 0;
+ XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_384_mod_inv_12(s, s, p384_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_384_mul_12(s, s, p384_norm_order);
+ }
+ err = sp_384_mod_12(s, s, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_384_mont_inv_order_12(s, s, tmp);
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#else
+ {
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_384_add_points_12(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 384)
@@ -29937,8 +30769,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_384_ctx {
@@ -29957,8 +30788,9 @@ typedef struct sp_ecc_verify_384_ctx {
sp_point_384 p2;
} sp_ecc_verify_384_ctx;
-int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
@@ -30112,8 +30944,9 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -30132,7 +30965,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_384* p1;
sp_point_384* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_384_point_new_12(heap, p1d, p1);
@@ -30173,70 +31006,9 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_384_from_mp(p2->y, 12, pY);
sp_384_from_mp(p2->z, 12, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_384_mod_inv_12(s, s, p384_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_384_mul_12(s, s, p384_norm_order);
- }
- err = sp_384_mod_12(s, s, p384_order);
+ err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_384_norm_12(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_384_mont_inv_order_12(s, s, tmp);
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#else
- {
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_384_proj_point_add_12(p1, p1, p2, tmp);
- if (sp_384_iszero_12(p1->z)) {
- if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
- sp_384_proj_point_dbl_12(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- p1->x[8] = 0;
- p1->x[9] = 0;
- p1->x[10] = 0;
- p1->x[11] = 0;
- XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_384_from_mp(u2, 12, r);
@@ -30258,16 +31030,16 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_384_cmp_12(u2, p384_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
- p384_mp_mod);
- *res = (int)(sp_384_cmp_12(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
+ p384_mp_mod);
+ *res = (sp_384_cmp_12(p1->x, u1) == 0);
}
}
}
@@ -30291,7 +31063,8 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
+static int sp_384_ecc_is_point_12(const sp_point_384* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -30354,7 +31127,7 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 pubd;
@@ -30388,7 +31161,8 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[12];
@@ -30442,12 +31216,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_384_cmp_12(pub->x, p384_mod) >= 0 ||
- sp_384_cmp_12(pub->y, p384_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(pub->x, p384_mod) >= 0) ||
+ (sp_384_cmp_12(pub->y, p384_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -30459,12 +31232,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_384_iszero_12(p->x) == 0) ||
- (sp_384_iszero_12(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) ||
+ (sp_384_iszero_12(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -30472,12 +31243,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_384_cmp_12(p->x, pub->x) != 0 ||
- sp_384_cmp_12(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(p->x, pub->x) != 0) ||
+ (sp_384_cmp_12(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -30667,7 +31437,7 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_384_from_mp(p->y, 12, pY);
sp_384_from_mp(p->z, 12, pZ);
- sp_384_map_12(p, p, tmp);
+ sp_384_map_12(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -30880,6 +31650,13182 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
}
#endif
#endif /* WOLFSSL_SP_384 */
+#ifdef WOLFSSL_SP_1024
+
+/* Point structure to use. */
+typedef struct sp_point_1024 {
+ /* X ordinate of point. */
+ sp_digit x[2 * 32];
+ /* Y ordinate of point. */
+ sp_digit y[2 * 32];
+ /* Z ordinate of point. */
+ sp_digit z[2 * 32];
+ /* Indicates point is at infinity. */
+ int infinity;
+} sp_point_1024;
+
+#ifndef WOLFSSL_SP_SMALL
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit tmp[16 * 2];
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r9, %[a]\n\t"
+ "mov r10, %[b]\n\t"
+ "mov r6, #64\n\t"
+ "add r6, r9\n\t"
+ "mov r12, r6\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #60\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov %[b], r8\n\t"
+ "sub %[b], %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add %[b], r10\n\t"
+ "\n2:\n\t"
+ "# Multiply Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply Done\n\t"
+ "add %[a], #4\n\t"
+ "sub %[b], #4\n\t"
+ "cmp %[a], r12\n\t"
+ "beq 3f\n\t"
+ "mov r6, r8\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r11\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #120\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[a], r9\n\t"
+ "mov %[b], r10\n\t"
+ :
+ : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+ );
+
+ XMEMCPY(r, tmp, sizeof(tmp));
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r6, #128\n\t"
+ "neg r6, r6\n\t"
+ "add sp, r6\n\t"
+ "mov r10, sp\n\t"
+ "mov r9, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #60\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov r2, r8\n\t"
+ "sub r2, %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add r2, r9\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+ "beq 4f\n\t"
+ "# Multiply * 2: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply * 2: Done\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "# Square: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r6\n\t"
+ "add r3, r6\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "mul r7, r7\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #15\n\t"
+ "lsl r6, r6, #17\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Square: Done\n\t"
+ "\n5:\n\t"
+ "add %[a], #4\n\t"
+ "sub r2, #4\n\t"
+ "mov r6, #64\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "beq 3f\n\t"
+ "cmp %[a], r2\n\t"
+ "bgt 3f\n\t"
+ "mov r7, r8\n\t"
+ "add r7, r9\n\t"
+ "cmp %[a], r7\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r10\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #120\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "mov %[a], r9\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[r], r11\n\t"
+ "mov %[a], r10\n\t"
+ "mov r3, #124\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "sub r3, #4\n\t"
+ "bge 4b\n\t"
+ "mov r6, #128\n\t"
+ "add sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
+ );
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "add r4, r5\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #4]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #12]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #20]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #28]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #36]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #44]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "ldr r4, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #52]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "ldr r4, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #60]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #60]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5"
+ );
+
+ return c;
+}
+
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r3, [%[a], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "ldr r6, [%[b], #4]\n\t"
+ "sub r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #0]\n\t"
+ "str r4, [%[a], #4]\n\t"
+ "ldr r3, [%[a], #8]\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "ldr r6, [%[b], #12]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #8]\n\t"
+ "str r4, [%[a], #12]\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "ldr r6, [%[b], #20]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #16]\n\t"
+ "str r4, [%[a], #20]\n\t"
+ "ldr r3, [%[a], #24]\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "ldr r6, [%[b], #28]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #24]\n\t"
+ "str r4, [%[a], #28]\n\t"
+ "ldr r3, [%[a], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "ldr r6, [%[b], #36]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #32]\n\t"
+ "str r4, [%[a], #36]\n\t"
+ "ldr r3, [%[a], #40]\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "ldr r6, [%[b], #44]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #40]\n\t"
+ "str r4, [%[a], #44]\n\t"
+ "ldr r3, [%[a], #48]\n\t"
+ "ldr r4, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "ldr r6, [%[b], #52]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #48]\n\t"
+ "str r4, [%[a], #52]\n\t"
+ "ldr r3, [%[a], #56]\n\t"
+ "ldr r4, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "ldr r6, [%[b], #60]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #56]\n\t"
+ "str r4, [%[a], #60]\n\t"
+ "ldr r3, [%[a], #64]\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "ldr r5, [%[b], #64]\n\t"
+ "ldr r6, [%[b], #68]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #64]\n\t"
+ "str r4, [%[a], #68]\n\t"
+ "ldr r3, [%[a], #72]\n\t"
+ "ldr r4, [%[a], #76]\n\t"
+ "ldr r5, [%[b], #72]\n\t"
+ "ldr r6, [%[b], #76]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #72]\n\t"
+ "str r4, [%[a], #76]\n\t"
+ "ldr r3, [%[a], #80]\n\t"
+ "ldr r4, [%[a], #84]\n\t"
+ "ldr r5, [%[b], #80]\n\t"
+ "ldr r6, [%[b], #84]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #80]\n\t"
+ "str r4, [%[a], #84]\n\t"
+ "ldr r3, [%[a], #88]\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "ldr r5, [%[b], #88]\n\t"
+ "ldr r6, [%[b], #92]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #88]\n\t"
+ "str r4, [%[a], #92]\n\t"
+ "ldr r3, [%[a], #96]\n\t"
+ "ldr r4, [%[a], #100]\n\t"
+ "ldr r5, [%[b], #96]\n\t"
+ "ldr r6, [%[b], #100]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #96]\n\t"
+ "str r4, [%[a], #100]\n\t"
+ "ldr r3, [%[a], #104]\n\t"
+ "ldr r4, [%[a], #108]\n\t"
+ "ldr r5, [%[b], #104]\n\t"
+ "ldr r6, [%[b], #108]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #104]\n\t"
+ "str r4, [%[a], #108]\n\t"
+ "ldr r3, [%[a], #112]\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "ldr r5, [%[b], #112]\n\t"
+ "ldr r6, [%[b], #116]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #112]\n\t"
+ "str r4, [%[a], #116]\n\t"
+ "ldr r3, [%[a], #120]\n\t"
+ "ldr r4, [%[a], #124]\n\t"
+ "ldr r5, [%[b], #120]\n\t"
+ "ldr r6, [%[b], #124]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a], #120]\n\t"
+ "str r4, [%[a], #124]\n\t"
+ "sbc %[c], %[c]\n\t"
+ : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r3", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[b], #0]\n\t"
+ "add r4, r5\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b], #4]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[b], #8]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "ldr r4, [%[a], #12]\n\t"
+ "ldr r5, [%[b], #12]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[b], #16]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "ldr r5, [%[b], #20]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[b], #24]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "ldr r4, [%[a], #28]\n\t"
+ "ldr r5, [%[b], #28]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[b], #32]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "ldr r4, [%[a], #36]\n\t"
+ "ldr r5, [%[b], #36]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[b], #40]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "ldr r5, [%[b], #44]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[b], #48]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "ldr r4, [%[a], #52]\n\t"
+ "ldr r5, [%[b], #52]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[b], #56]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "ldr r4, [%[a], #60]\n\t"
+ "ldr r5, [%[b], #60]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[b], #64]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "ldr r5, [%[b], #68]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[b], #72]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "ldr r4, [%[a], #76]\n\t"
+ "ldr r5, [%[b], #76]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[b], #80]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "ldr r4, [%[a], #84]\n\t"
+ "ldr r5, [%[b], #84]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[b], #88]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "ldr r5, [%[b], #92]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[b], #96]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "ldr r4, [%[a], #100]\n\t"
+ "ldr r5, [%[b], #100]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[b], #104]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "ldr r4, [%[a], #108]\n\t"
+ "ldr r5, [%[b], #108]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[b], #112]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "ldr r5, [%[b], #116]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[b], #120]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "ldr r4, [%[a], #124]\n\t"
+ "ldr r5, [%[b], #124]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r], #124]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5"
+ );
+
+ return c;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<16; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 16; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit* z0 = r;
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit b1[16];
+ sp_digit z2[32];
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
+
+ ca = sp_1024_add_16(a1, a, &a[16]);
+ cb = sp_1024_add_16(b1, b, &b[16]);
+ u = ca & cb;
+ sp_1024_mul_16(z1, a1, b1);
+ sp_1024_mul_16(z2, &a[16], &b[16]);
+ sp_1024_mul_16(z0, a, b);
+ sp_1024_mask_16(r + 32, a1, 0 - cb);
+ sp_1024_mask_16(b1, b1, 0 - ca);
+ u += sp_1024_add_16(r + 32, r + 32, b1);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ sp_digit* z0 = r;
+ sp_digit z2[32];
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit u;
+
+ u = sp_1024_add_16(a1, a, &a[16]);
+ sp_1024_sqr_16(z1, a1);
+ sp_1024_sqr_16(z2, &a[16]);
+ sp_1024_sqr_16(z0, a);
+ sp_1024_mask_16(r + 32, a1, 0 - u);
+ u += sp_1024_add_16(r + 32, r + 32, r + 32);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+#else
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit tmp[32 * 2];
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r9, %[a]\n\t"
+ "mov r10, %[b]\n\t"
+ "mov r6, #128\n\t"
+ "add r6, r9\n\t"
+ "mov r12, r6\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #124\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov %[b], r8\n\t"
+ "sub %[b], %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add %[b], r10\n\t"
+ "\n2:\n\t"
+ "# Multiply Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [%[b]]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply Done\n\t"
+ "add %[a], #4\n\t"
+ "sub %[b], #4\n\t"
+ "cmp %[a], r12\n\t"
+ "beq 3f\n\t"
+ "mov r6, r8\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r11\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #248\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[a], r9\n\t"
+ "mov %[b], r10\n\t"
+ :
+ : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+ );
+
+ XMEMCPY(r, tmp, sizeof(tmp));
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r8, r3\n\t"
+ "mov r11, %[r]\n\t"
+ "mov r6, #1\n\t"
+ "lsl r6, r6, #8\n\t"
+ "neg r6, r6\n\t"
+ "add sp, r6\n\t"
+ "mov r10, sp\n\t"
+ "mov r9, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #124\n\t"
+ "mov %[a], r8\n\t"
+ "sub %[a], r6\n\t"
+ "sbc r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], r6\n\t"
+ "mov r2, r8\n\t"
+ "sub r2, %[a]\n\t"
+ "add %[a], r9\n\t"
+ "add r2, r9\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+ "beq 4f\n\t"
+ "# Multiply * 2: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r7, [r2]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Multiply * 2: Done\n\t"
+ "bal 5f\n\t"
+ "\n4:\n\t"
+ "# Square: Start\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r6\n\t"
+ "add r3, r6\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "mul r7, r7\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #15\n\t"
+ "lsl r6, r6, #17\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# Square: Done\n\t"
+ "\n5:\n\t"
+ "add %[a], #4\n\t"
+ "sub r2, #4\n\t"
+ "mov r6, #128\n\t"
+ "add r6, r9\n\t"
+ "cmp %[a], r6\n\t"
+ "beq 3f\n\t"
+ "cmp %[a], r2\n\t"
+ "bgt 3f\n\t"
+ "mov r7, r8\n\t"
+ "add r7, r9\n\t"
+ "cmp %[a], r7\n\t"
+ "ble 2b\n\t"
+ "\n3:\n\t"
+ "mov %[r], r10\n\t"
+ "mov r7, r8\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r7, #4\n\t"
+ "mov r8, r7\n\t"
+ "mov r6, #248\n\t"
+ "cmp r7, r6\n\t"
+ "ble 1b\n\t"
+ "mov %[a], r9\n\t"
+ "str r3, [%[r], r7]\n\t"
+ "mov %[r], r11\n\t"
+ "mov %[a], r10\n\t"
+ "mov r3, #252\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "sub r3, #4\n\t"
+ "bge 4b\n\t"
+ "mov r6, #1\n\t"
+ "lsl r6, r6, #8\n\t"
+ "add sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
+ );
+}
+
+#endif /* !WOLFSSL_SP_SMALL */
+/* The modulus (prime) of the curve P1024. */
+static const sp_digit p1024_mod[32] = {
+ 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823,
+ 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8,
+ 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4,
+ 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27,
+ 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198,
+ 0x0a563fda,0x997abb1f
+};
+/* The Montogmery normalizer for modulus of the curve P1024. */
+static const sp_digit p1024_norm_mod[32] = {
+ 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc,
+ 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57,
+ 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b,
+ 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8,
+ 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67,
+ 0xf5a9c025,0x668544e0
+};
+/* The Montogmery multiplier for modulus of the curve P1024. */
+static sp_digit p1024_mp_mod = 0x7c8f2f3d;
+#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
+/* The order of the curve P1024. */
+static const sp_digit p1024_order[32] = {
+ 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08,
+ 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a,
+ 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd,
+ 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9,
+ 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466,
+ 0xc2958ff6,0x265eaec7
+};
+#endif
+/* The base point of curve P1024. */
+static const sp_point_1024 p1024_base = {
+ /* X ordinate */
+ {
+ 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5,
+ 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339,
+ 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7,
+ 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0,
+ 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005,
+ 0x332c29ad,0x53fc09ee,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Y ordinate */
+ {
+ 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a,
+ 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80,
+ 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c,
+ 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4,
+ 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053,
+ 0x3f6009f1,0x0a824906,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Z ordinate */
+ {
+ 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* infinity */
+ 0
+};
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+ __asm__ __volatile__ (
+ "mov r7, %[a]\n\t"
+ "add r7, #128\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, %[c]\n\t"
+ "ldr r3, [%[a]]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "ldr r6, [%[b], #4]\n\t"
+ "sbc r3, r5\n\t"
+ "sbc r4, r6\n\t"
+ "str r3, [%[a]]\n\t"
+ "str r4, [%[a], #4]\n\t"
+ "sbc %[c], %[c]\n\t"
+ "add %[a], #8\n\t"
+ "add %[b], #8\n\t"
+ "cmp %[a], r7\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r3", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+SP_NOINLINE static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, sp_digit m)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r5, #128\n\t"
+ "mov r8, r5\n\t"
+ "mov r7, #0\n\t"
+ "1:\n\t"
+ "ldr r6, [%[b], r7]\n\t"
+ "and r6, %[m]\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, %[c]\n\t"
+ "ldr r5, [%[a], r7]\n\t"
+ "sbc r5, r6\n\t"
+ "sbc %[c], %[c]\n\t"
+ "str r5, [%[r], r7]\n\t"
+ "add r7, #4\n\t"
+ "cmp r7, r8\n\t"
+ "blt 1b\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r5", "r6", "r7", "r8"
+ );
+
+ return c;
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r7, #0\n\t"
+ "add r6, #128\n\t"
+ "sub r7, #1\n\t"
+ "\n1:\n\t"
+ "add %[c], r7\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Mul a by digit b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision digit.
+ */
+SP_NOINLINE static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a,
+ sp_digit b)
+{
+ __asm__ __volatile__ (
+ "mov r6, #128\n\t"
+ "add r6, %[a]\n\t"
+ "mov r8, %[r]\n\t"
+ "mov r9, r6\n\t"
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r5, #0\n\t"
+ "# A[] * B\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsl r6, r6, #16\n\t"
+ "lsl r7, %[b], #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r3, r7\n\t"
+ "adc r4, %[r]\n\t"
+ "adc r5, %[r]\n\t"
+ "lsr r7, %[b], #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "ldr r6, [%[a]]\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, %[b], #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "lsl r7, %[b], #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r3, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc r5, %[r]\n\t"
+ "# A[] * B - Done\n\t"
+ "mov %[r], r8\n\t"
+ "str r3, [%[r]]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "add %[r], #4\n\t"
+ "add %[a], #4\n\t"
+ "mov r8, %[r]\n\t"
+ "cmp %[a], r9\n\t"
+ "blt 1b\n\t"
+ "str r3, [%[r]]\n\t"
+ : [r] "+r" (r), [a] "+r" (a)
+ : [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
+ );
+}
+
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ *
+ * Note that this is an approximate div. It may give an answer 1 larger.
+ */
+SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+ sp_digit r = 0;
+
+ __asm__ __volatile__ (
+ "lsr r5, %[div], #1\n\t"
+ "add r5, #1\n\t"
+ "mov r8, %[d0]\n\t"
+ "mov r9, %[d1]\n\t"
+ "# Do top 32\n\t"
+ "mov r6, r5\n\t"
+ "sub r6, %[d1]\n\t"
+ "sbc r6, r6\n\t"
+ "add %[r], %[r]\n\t"
+ "sub %[r], r6\n\t"
+ "and r6, r5\n\t"
+ "sub %[d1], r6\n\t"
+ "# Next 30 bits\n\t"
+ "mov r4, #29\n\t"
+ "1:\n\t"
+ "lsl %[d0], %[d0], #1\n\t"
+ "adc %[d1], %[d1]\n\t"
+ "mov r6, r5\n\t"
+ "sub r6, %[d1]\n\t"
+ "sbc r6, r6\n\t"
+ "add %[r], %[r]\n\t"
+ "sub %[r], r6\n\t"
+ "and r6, r5\n\t"
+ "sub %[d1], r6\n\t"
+ "sub r4, #1\n\t"
+ "bpl 1b\n\t"
+ "mov r7, #0\n\t"
+ "add %[r], %[r]\n\t"
+ "add %[r], #1\n\t"
+ "# r * div - Start\n\t"
+ "lsl %[d1], %[r], #16\n\t"
+ "lsl r4, %[div], #16\n\t"
+ "lsr %[d1], %[d1], #16\n\t"
+ "lsr r4, r4, #16\n\t"
+ "mul r4, %[d1]\n\t"
+ "lsr r6, %[div], #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r5, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r7\n\t"
+ "lsr %[d1], %[r], #16\n\t"
+ "mul r6, %[d1]\n\t"
+ "add r5, r6\n\t"
+ "lsl r6, %[div], #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r6, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r6\n\t"
+ "# r * div - Done\n\t"
+ "mov %[d1], r8\n\t"
+ "sub %[d1], r4\n\t"
+ "mov r4, %[d1]\n\t"
+ "mov %[d1], r9\n\t"
+ "sbc %[d1], r5\n\t"
+ "mov r5, %[d1]\n\t"
+ "add %[r], r5\n\t"
+ "# r * div - Start\n\t"
+ "lsl %[d1], %[r], #16\n\t"
+ "lsl r4, %[div], #16\n\t"
+ "lsr %[d1], %[d1], #16\n\t"
+ "lsr r4, r4, #16\n\t"
+ "mul r4, %[d1]\n\t"
+ "lsr r6, %[div], #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r5, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r7\n\t"
+ "lsr %[d1], %[r], #16\n\t"
+ "mul r6, %[d1]\n\t"
+ "add r5, r6\n\t"
+ "lsl r6, %[div], #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r6, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r6\n\t"
+ "# r * div - Done\n\t"
+ "mov %[d1], r8\n\t"
+ "mov r6, r9\n\t"
+ "sub r4, %[d1], r4\n\t"
+ "sbc r6, r5\n\t"
+ "mov r5, r6\n\t"
+ "add %[r], r5\n\t"
+ "# r * div - Start\n\t"
+ "lsl %[d1], %[r], #16\n\t"
+ "lsl r4, %[div], #16\n\t"
+ "lsr %[d1], %[d1], #16\n\t"
+ "lsr r4, r4, #16\n\t"
+ "mul r4, %[d1]\n\t"
+ "lsr r6, %[div], #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r5, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r7\n\t"
+ "lsr %[d1], %[r], #16\n\t"
+ "mul r6, %[d1]\n\t"
+ "add r5, r6\n\t"
+ "lsl r6, %[div], #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "mul %[d1], r6\n\t"
+ "lsr r6, %[d1], #16\n\t"
+ "lsl %[d1], %[d1], #16\n\t"
+ "add r4, %[d1]\n\t"
+ "adc r5, r6\n\t"
+ "# r * div - Done\n\t"
+ "mov %[d1], r8\n\t"
+ "mov r6, r9\n\t"
+ "sub r4, %[d1], r4\n\t"
+ "sbc r6, r5\n\t"
+ "mov r5, r6\n\t"
+ "add %[r], r5\n\t"
+ "mov r6, %[div]\n\t"
+ "sub r6, r4\n\t"
+ "sbc r6, r6\n\t"
+ "sub %[r], r6\n\t"
+ : [r] "+r" (r)
+ : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
+ : "r4", "r5", "r7", "r6", "r8", "r9"
+ );
+ return r;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<32; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Compare a with b in constant time.
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ * return -ve, 0 or +ve if a is less than, equal to or greater than b
+ * respectively.
+ */
+SP_NOINLINE static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b)
+{
+ sp_digit r = 0;
+
+
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mvn r3, r3\n\t"
+ "mov r6, #124\n\t"
+ "1:\n\t"
+ "ldr r7, [%[a], r6]\n\t"
+ "ldr r5, [%[b], r6]\n\t"
+ "and r7, r3\n\t"
+ "and r5, r3\n\t"
+ "mov r4, r7\n\t"
+ "sub r7, r5\n\t"
+ "sbc r7, r7\n\t"
+ "add %[r], r7\n\t"
+ "mvn r7, r7\n\t"
+ "and r3, r7\n\t"
+ "sub r5, r4\n\t"
+ "sbc r7, r7\n\t"
+ "sub %[r], r7\n\t"
+ "mvn r7, r7\n\t"
+ "and r3, r7\n\t"
+ "sub r6, #4\n\t"
+ "cmp r6, #0\n\t"
+ "bge 1b\n\t"
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "r3", "r4", "r5", "r6", "r7"
+ );
+
+ return r;
+}
+
+/* Divide d in a and put remainder into r (m*d + r = a)
+ * m is not calculated as it is not needed at this time.
+ *
+ * a Number to be divided.
+ * d Number to divide with.
+ * m Multiplier result.
+ * r Remainder from the division.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m,
+ sp_digit* r)
+{
+ sp_digit t1[64], t2[33];
+ sp_digit div, r1;
+ int i;
+
+ (void)m;
+
+ div = d[31];
+ XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
+ for (i=31; i>=0; i--) {
+ sp_digit hi = t1[32 + i] - (t1[32 + i] == div);
+ r1 = div_1024_word_32(hi, t1[32 + i - 1], div);
+
+ sp_1024_mul_d_32(t2, d, r1);
+ t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2);
+ t1[32 + i] -= t2[32];
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ }
+
+ r1 = sp_1024_cmp_32(t1, d) >= 0;
+ sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
+
+ return MP_OKAY;
+}
+
+/* Reduce a modulo m into r. (r = a mod m)
+ *
+ * r A single precision number that is the reduced result.
+ * a A single precision number that is to be reduced.
+ * m A single precision number that is the modulus to reduce with.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ return sp_1024_div_32(a, m, NULL, r);
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
+{
+ sp_1024_mul_32(r, a, p1024_norm_mod);
+ return sp_1024_mod_32(r, r, m);
+}
+
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp,
+ sp_point_1024** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_1024.
+ *
+ * p Point of type sp_point_1024 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_1024_point_from_ecc_point_32(sp_point_1024* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_1024_from_mp(p->x, 32, pm->x);
+ sp_1024_from_mp(p->y, 32, pm->y);
+ sp_1024_from_mp(p->z, 32, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
+ r->used = 32;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_1024 to type ecc_point.
+ *
+ * p Point of type sp_point_1024.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_1024_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
+/* Reduce the number back to 1024 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m,
+ sp_digit mp)
+{
+ sp_digit ca = 0;
+
+ __asm__ __volatile__ (
+ "mov r8, %[mp]\n\t"
+ "mov r12, %[ca]\n\t"
+ "mov r14, %[m]\n\t"
+ "mov r9, %[a]\n\t"
+ "mov r4, #0\n\t"
+ "# i = 0\n\t"
+ "mov r11, r4\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "mov %[ca], #0\n\t"
+ "# mu = a[i] * mp\n\t"
+ "mov %[mp], r8\n\t"
+ "ldr %[a], [%[a]]\n\t"
+ "mul %[mp], %[a]\n\t"
+ "mov %[m], r14\n\t"
+ "mov r10, r9\n\t"
+ "\n2:\n\t"
+ "# a[i+j] += m[j] * mu\n\t"
+ "mov %[a], r10\n\t"
+ "ldr %[a], [%[a]]\n\t"
+ "mov %[ca], #0\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "# Multiply m[j] and mu - Start\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsl r6, %[mp], #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add %[a], r7\n\t"
+ "adc r5, %[ca]\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add %[a], r6\n\t"
+ "adc r5, r7\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsr r6, %[mp], #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r5, r7\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add %[a], r6\n\t"
+ "adc r5, r7\n\t"
+ "# Multiply m[j] and mu - Done\n\t"
+ "add r4, %[a]\n\t"
+ "adc r5, %[ca]\n\t"
+ "mov %[a], r10\n\t"
+ "str r4, [%[a]]\n\t"
+ "mov r6, #4\n\t"
+ "add %[m], #4\n\t"
+ "add r10, r6\n\t"
+ "mov r4, #124\n\t"
+ "add r4, r9\n\t"
+ "cmp r10, r4\n\t"
+ "blt 2b\n\t"
+ "# a[i+31] += m[31] * mu\n\t"
+ "mov %[ca], #0\n\t"
+ "mov r4, r12\n\t"
+ "mov %[a], #0\n\t"
+ "# Multiply m[31] and mu - Start\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsl r6, %[mp], #16\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r6, r6, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r5, r7\n\t"
+ "adc r4, %[ca]\n\t"
+ "adc %[a], %[ca]\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r5, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc %[a], %[ca]\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsr r6, %[mp], #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r7, r6\n\t"
+ "add r4, r7\n\t"
+ "adc %[a], %[ca]\n\t"
+ "ldr r7, [%[m]]\n\t"
+ "lsl r7, r7, #16\n\t"
+ "lsr r7, r7, #16\n\t"
+ "mul r6, r7\n\t"
+ "lsr r7, r6, #16\n\t"
+ "lsl r6, r6, #16\n\t"
+ "add r5, r6\n\t"
+ "adc r4, r7\n\t"
+ "adc %[a], %[ca]\n\t"
+ "# Multiply m[31] and mu - Done\n\t"
+ "mov %[ca], %[a]\n\t"
+ "mov %[a], r10\n\t"
+ "ldr r7, [%[a], #4]\n\t"
+ "ldr %[a], [%[a]]\n\t"
+ "mov r6, #0\n\t"
+ "add r5, %[a]\n\t"
+ "adc r7, r4\n\t"
+ "adc %[ca], r6\n\t"
+ "mov %[a], r10\n\t"
+ "str r5, [%[a]]\n\t"
+ "str r7, [%[a], #4]\n\t"
+ "# i += 1\n\t"
+ "mov r6, #4\n\t"
+ "add r9, r6\n\t"
+ "add r11, r6\n\t"
+ "mov r12, %[ca]\n\t"
+ "mov %[a], r9\n\t"
+ "mov r4, #128\n\t"
+ "cmp r11, r4\n\t"
+ "blt 1b\n\t"
+ "ldr r6, [%[m]]\n\t"
+ "neg %[ca], %[ca]\n\t"
+ "sub r6, r7\n\t"
+ "sbc r6, r6\n\t"
+ "orr %[ca], r6\n\t"
+ "mov %[m], r14\n\t"
+ : [ca] "+r" (ca), [a] "+r" (a)
+ : [m] "r" (m), [mp] "r" (mp)
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
+ );
+
+ sp_1024_cond_sub_32(a - 32, a, m, ca);
+}
+
+/* Multiply two Montogmery form numbers mod the modulus (prime).
+ * (r = a * b mod m)
+ *
+ * r Result of multiplication.
+ * a First number to multiply in Montogmery form.
+ * b Second number to multiply in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
+{
+ sp_1024_mul_32(r, a, b);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Square the Montgomery form number. (r = a * a mod m)
+ *
+ * r Result of squaring.
+ * a Number to square in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
+{
+ sp_1024_sqr_32(r, a);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Mod-2 for the P1024 curve. */
+static const uint8_t p1024_mod_minus_2[] = {
+ 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
+ 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
+ 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
+ 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
+ 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
+ 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
+ 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
+ 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
+ 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
+ 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
+ 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
+ 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
+ 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
+ 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
+ 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
+ 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
+ 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
+ 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
+ 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
+};
+
+/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
+ * P1024 curve. (r = 1 / a mod m)
+ *
+ * r Inverse result.
+ * a Number to invert.
+ * td Temporary data.
+ */
+static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a,
+ sp_digit* td)
+{
+ sp_digit* t = td;
+ int i;
+ int j;
+ sp_digit table[32][2 * 32];
+
+ XMEMCPY(table[0], a, sizeof(sp_digit) * 32);
+ for (i = 1; i < 6; i++) {
+ sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod);
+ }
+ for (i = 1; i < 32; i++) {
+ sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
+ }
+
+ XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32);
+ for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
+ for (j = 0; j < p1024_mod_minus_2[i]; j++) {
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ }
+ sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
+ p1024_mp_mod);
+ }
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod);
+}
+
+/* Normalize the values in each word to 32.
+ *
+ * a Array of sp_digit to normalize.
+ */
+#define sp_1024_norm_32(a)
+
+/* Map the Montgomery form projective coordinate point to an affine point.
+ *
+ * r Resulting affine coordinate point.
+ * p Montgomery form projective coordinate point.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p,
+ sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ int32_t n;
+
+ sp_1024_mont_inv_32(t1, p->z, t + 2*32);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ /* x /= z^2 */
+ sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U);
+ sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod);
+ /* Reduce x to less than modulus */
+ n = sp_1024_cmp_32(r->x, p1024_mod);
+ sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->x);
+
+ /* y /= z^3 */
+ sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U);
+ sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod);
+ /* Reduce y to less than modulus */
+ n = sp_1024_cmp_32(r->y, p1024_mod);
+ sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->y);
+
+ XMEMSET(r->z, 0, sizeof(r->z));
+ r->z[0] = 1;
+
+}
+
+/* Add two Montgomery form numbers (r = a + b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "add r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[b], #56]\n\t"
+ "ldr r7, [%[b], #60]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[b], #72]\n\t"
+ "ldr r7, [%[b], #76]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[b], #88]\n\t"
+ "ldr r7, [%[b], #92]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[b], #104]\n\t"
+ "ldr r7, [%[b], #108]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[b], #120]\n\t"
+ "ldr r7, [%[b], #124]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "mov %[b], #0\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "adc %[b], %[b]\n\t"
+ "sub r7, r5\n\t"
+ "neg %[b], %[b]\n\t"
+ "sbc r7, r7\n\t"
+ "orr %[b], r7\n\t"
+ "ldr r4, [%[r], #0]\n\t"
+ "ldr r5, [%[r], #4]\n\t"
+ "ldr r6, [%[m], #0]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[r], #8]\n\t"
+ "ldr r5, [%[r], #12]\n\t"
+ "ldr r6, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[r], #16]\n\t"
+ "ldr r5, [%[r], #20]\n\t"
+ "ldr r6, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[r], #24]\n\t"
+ "ldr r5, [%[r], #28]\n\t"
+ "ldr r6, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[r], #32]\n\t"
+ "ldr r5, [%[r], #36]\n\t"
+ "ldr r6, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[r], #40]\n\t"
+ "ldr r5, [%[r], #44]\n\t"
+ "ldr r6, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[r], #48]\n\t"
+ "ldr r5, [%[r], #52]\n\t"
+ "ldr r6, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[r], #56]\n\t"
+ "ldr r5, [%[r], #60]\n\t"
+ "ldr r6, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[r], #64]\n\t"
+ "ldr r5, [%[r], #68]\n\t"
+ "ldr r6, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[r], #72]\n\t"
+ "ldr r5, [%[r], #76]\n\t"
+ "ldr r6, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[r], #80]\n\t"
+ "ldr r5, [%[r], #84]\n\t"
+ "ldr r6, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[r], #88]\n\t"
+ "ldr r5, [%[r], #92]\n\t"
+ "ldr r6, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[r], #96]\n\t"
+ "ldr r5, [%[r], #100]\n\t"
+ "ldr r6, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[r], #104]\n\t"
+ "ldr r5, [%[r], #108]\n\t"
+ "ldr r6, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[r], #112]\n\t"
+ "ldr r5, [%[r], #116]\n\t"
+ "ldr r6, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[r], #120]\n\t"
+ "ldr r5, [%[r], #124]\n\t"
+ "ldr r6, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+}
+
+/* Double a Montgomery form number (r = a + a % m).
+ *
+ * r Result of doubling.
+ * a Number to double in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "add r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[a], #40]\n\t"
+ "ldr r7, [%[a], #44]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[a], #56]\n\t"
+ "ldr r7, [%[a], #60]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[a], #72]\n\t"
+ "ldr r7, [%[a], #76]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "str r6, [%[r], #72]\n\t"
+ "str r7, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[a], #88]\n\t"
+ "ldr r7, [%[a], #92]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "str r6, [%[r], #88]\n\t"
+ "str r7, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[a], #104]\n\t"
+ "ldr r7, [%[a], #108]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "str r6, [%[r], #104]\n\t"
+ "str r7, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[a], #120]\n\t"
+ "ldr r7, [%[a], #124]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "str r6, [%[r], #120]\n\t"
+ "str r7, [%[r], #124]\n\t"
+ "mov r3, #0\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r3, r3\n\t"
+ "sub r4, r7\n\t"
+ "neg r3, r3\n\t"
+ "sbc r4, r4\n\t"
+ "orr r3, r4\n\t"
+ "ldr r4, [%[r], #0]\n\t"
+ "ldr r5, [%[r], #4]\n\t"
+ "ldr r6, [%[m], #0]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[r], #8]\n\t"
+ "ldr r5, [%[r], #12]\n\t"
+ "ldr r6, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[r], #16]\n\t"
+ "ldr r5, [%[r], #20]\n\t"
+ "ldr r6, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[r], #24]\n\t"
+ "ldr r5, [%[r], #28]\n\t"
+ "ldr r6, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[r], #32]\n\t"
+ "ldr r5, [%[r], #36]\n\t"
+ "ldr r6, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[r], #40]\n\t"
+ "ldr r5, [%[r], #44]\n\t"
+ "ldr r6, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[r], #48]\n\t"
+ "ldr r5, [%[r], #52]\n\t"
+ "ldr r6, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[r], #56]\n\t"
+ "ldr r5, [%[r], #60]\n\t"
+ "ldr r6, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[r], #64]\n\t"
+ "ldr r5, [%[r], #68]\n\t"
+ "ldr r6, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[r], #72]\n\t"
+ "ldr r5, [%[r], #76]\n\t"
+ "ldr r6, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[r], #80]\n\t"
+ "ldr r5, [%[r], #84]\n\t"
+ "ldr r6, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[r], #88]\n\t"
+ "ldr r5, [%[r], #92]\n\t"
+ "ldr r6, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[r], #96]\n\t"
+ "ldr r5, [%[r], #100]\n\t"
+ "ldr r6, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[r], #104]\n\t"
+ "ldr r5, [%[r], #108]\n\t"
+ "ldr r6, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[r], #112]\n\t"
+ "ldr r5, [%[r], #116]\n\t"
+ "ldr r6, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[r], #120]\n\t"
+ "ldr r5, [%[r], #124]\n\t"
+ "ldr r6, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r3"
+ );
+}
+
+/* Triple a Montgomery form number (r = a + a + a % m).
+ *
+ * r Result of Tripling.
+ * a Number to triple in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r7, [%[a], #12]\n\t"
+ "add r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r7, [%[a], #28]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[a], #40]\n\t"
+ "ldr r7, [%[a], #44]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[a], #56]\n\t"
+ "ldr r7, [%[a], #60]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[a], #72]\n\t"
+ "ldr r7, [%[a], #76]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "str r6, [%[r], #72]\n\t"
+ "str r7, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[a], #88]\n\t"
+ "ldr r7, [%[a], #92]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "str r6, [%[r], #88]\n\t"
+ "str r7, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[a], #104]\n\t"
+ "ldr r7, [%[a], #108]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "str r6, [%[r], #104]\n\t"
+ "str r7, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[a], #120]\n\t"
+ "ldr r7, [%[a], #124]\n\t"
+ "adc r4, r4\n\t"
+ "adc r5, r5\n\t"
+ "adc r6, r6\n\t"
+ "adc r7, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "str r6, [%[r], #120]\n\t"
+ "str r7, [%[r], #124]\n\t"
+ "mov r3, #0\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r3, r3\n\t"
+ "sub r4, r7\n\t"
+ "neg r3, r3\n\t"
+ "sbc r4, r4\n\t"
+ "orr r3, r4\n\t"
+ "ldr r4, [%[r], #0]\n\t"
+ "ldr r5, [%[r], #4]\n\t"
+ "ldr r6, [%[m], #0]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[r], #8]\n\t"
+ "ldr r5, [%[r], #12]\n\t"
+ "ldr r6, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[r], #16]\n\t"
+ "ldr r5, [%[r], #20]\n\t"
+ "ldr r6, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[r], #24]\n\t"
+ "ldr r5, [%[r], #28]\n\t"
+ "ldr r6, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[r], #32]\n\t"
+ "ldr r5, [%[r], #36]\n\t"
+ "ldr r6, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[r], #40]\n\t"
+ "ldr r5, [%[r], #44]\n\t"
+ "ldr r6, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[r], #48]\n\t"
+ "ldr r5, [%[r], #52]\n\t"
+ "ldr r6, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[r], #56]\n\t"
+ "ldr r5, [%[r], #60]\n\t"
+ "ldr r6, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[r], #64]\n\t"
+ "ldr r5, [%[r], #68]\n\t"
+ "ldr r6, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[r], #72]\n\t"
+ "ldr r5, [%[r], #76]\n\t"
+ "ldr r6, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[r], #80]\n\t"
+ "ldr r5, [%[r], #84]\n\t"
+ "ldr r6, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[r], #88]\n\t"
+ "ldr r5, [%[r], #92]\n\t"
+ "ldr r6, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[r], #96]\n\t"
+ "ldr r5, [%[r], #100]\n\t"
+ "ldr r6, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[r], #104]\n\t"
+ "ldr r5, [%[r], #108]\n\t"
+ "ldr r6, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[r], #112]\n\t"
+ "ldr r5, [%[r], #116]\n\t"
+ "ldr r6, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[r], #120]\n\t"
+ "ldr r5, [%[r], #124]\n\t"
+ "ldr r6, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "and r6, r3\n\t"
+ "and r7, r3\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[r], #0]\n\t"
+ "ldr r7, [%[r], #4]\n\t"
+ "add r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[r], #8]\n\t"
+ "ldr r7, [%[r], #12]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[r], #16]\n\t"
+ "ldr r7, [%[r], #20]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #16]\n\t"
+ "str r7, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[r], #24]\n\t"
+ "ldr r7, [%[r], #28]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[r], #32]\n\t"
+ "ldr r7, [%[r], #36]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #32]\n\t"
+ "str r7, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[r], #40]\n\t"
+ "ldr r7, [%[r], #44]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[r], #48]\n\t"
+ "ldr r7, [%[r], #52]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #48]\n\t"
+ "str r7, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[r], #56]\n\t"
+ "ldr r7, [%[r], #60]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[r], #64]\n\t"
+ "ldr r7, [%[r], #68]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #64]\n\t"
+ "str r7, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[r], #72]\n\t"
+ "ldr r7, [%[r], #76]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #72]\n\t"
+ "str r7, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[r], #80]\n\t"
+ "ldr r7, [%[r], #84]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #80]\n\t"
+ "str r7, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[r], #88]\n\t"
+ "ldr r7, [%[r], #92]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #88]\n\t"
+ "str r7, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[r], #96]\n\t"
+ "ldr r7, [%[r], #100]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #96]\n\t"
+ "str r7, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[r], #104]\n\t"
+ "ldr r7, [%[r], #108]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #104]\n\t"
+ "str r7, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[r], #112]\n\t"
+ "ldr r7, [%[r], #116]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #112]\n\t"
+ "str r7, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[r], #120]\n\t"
+ "ldr r7, [%[r], #124]\n\t"
+ "adc r6, r4\n\t"
+ "adc r7, r5\n\t"
+ "str r6, [%[r], #120]\n\t"
+ "str r7, [%[r], #124]\n\t"
+ "mov r3, #0\n\t"
+ "ldr r5, [%[m], #124]\n\t"
+ "adc r3, r3\n\t"
+ "sub r5, r7\n\t"
+ "neg r3, r3\n\t"
+ "sbc r5, r5\n\t"
+ "orr r3, r5\n\t"
+ "ldr r6, [%[r], #0]\n\t"
+ "ldr r7, [%[r], #4]\n\t"
+ "ldr r4, [%[m], #0]\n\t"
+ "ldr r5, [%[m], #4]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sub r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #0]\n\t"
+ "str r7, [%[r], #4]\n\t"
+ "ldr r6, [%[r], #8]\n\t"
+ "ldr r7, [%[r], #12]\n\t"
+ "ldr r4, [%[m], #8]\n\t"
+ "ldr r5, [%[m], #12]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #8]\n\t"
+ "str r7, [%[r], #12]\n\t"
+ "ldr r6, [%[r], #16]\n\t"
+ "ldr r7, [%[r], #20]\n\t"
+ "ldr r4, [%[m], #16]\n\t"
+ "ldr r5, [%[m], #20]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #16]\n\t"
+ "str r7, [%[r], #20]\n\t"
+ "ldr r6, [%[r], #24]\n\t"
+ "ldr r7, [%[r], #28]\n\t"
+ "ldr r4, [%[m], #24]\n\t"
+ "ldr r5, [%[m], #28]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #24]\n\t"
+ "str r7, [%[r], #28]\n\t"
+ "ldr r6, [%[r], #32]\n\t"
+ "ldr r7, [%[r], #36]\n\t"
+ "ldr r4, [%[m], #32]\n\t"
+ "ldr r5, [%[m], #36]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #32]\n\t"
+ "str r7, [%[r], #36]\n\t"
+ "ldr r6, [%[r], #40]\n\t"
+ "ldr r7, [%[r], #44]\n\t"
+ "ldr r4, [%[m], #40]\n\t"
+ "ldr r5, [%[m], #44]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #40]\n\t"
+ "str r7, [%[r], #44]\n\t"
+ "ldr r6, [%[r], #48]\n\t"
+ "ldr r7, [%[r], #52]\n\t"
+ "ldr r4, [%[m], #48]\n\t"
+ "ldr r5, [%[m], #52]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #48]\n\t"
+ "str r7, [%[r], #52]\n\t"
+ "ldr r6, [%[r], #56]\n\t"
+ "ldr r7, [%[r], #60]\n\t"
+ "ldr r4, [%[m], #56]\n\t"
+ "ldr r5, [%[m], #60]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #56]\n\t"
+ "str r7, [%[r], #60]\n\t"
+ "ldr r6, [%[r], #64]\n\t"
+ "ldr r7, [%[r], #68]\n\t"
+ "ldr r4, [%[m], #64]\n\t"
+ "ldr r5, [%[m], #68]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #64]\n\t"
+ "str r7, [%[r], #68]\n\t"
+ "ldr r6, [%[r], #72]\n\t"
+ "ldr r7, [%[r], #76]\n\t"
+ "ldr r4, [%[m], #72]\n\t"
+ "ldr r5, [%[m], #76]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #72]\n\t"
+ "str r7, [%[r], #76]\n\t"
+ "ldr r6, [%[r], #80]\n\t"
+ "ldr r7, [%[r], #84]\n\t"
+ "ldr r4, [%[m], #80]\n\t"
+ "ldr r5, [%[m], #84]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #80]\n\t"
+ "str r7, [%[r], #84]\n\t"
+ "ldr r6, [%[r], #88]\n\t"
+ "ldr r7, [%[r], #92]\n\t"
+ "ldr r4, [%[m], #88]\n\t"
+ "ldr r5, [%[m], #92]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #88]\n\t"
+ "str r7, [%[r], #92]\n\t"
+ "ldr r6, [%[r], #96]\n\t"
+ "ldr r7, [%[r], #100]\n\t"
+ "ldr r4, [%[m], #96]\n\t"
+ "ldr r5, [%[m], #100]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #96]\n\t"
+ "str r7, [%[r], #100]\n\t"
+ "ldr r6, [%[r], #104]\n\t"
+ "ldr r7, [%[r], #108]\n\t"
+ "ldr r4, [%[m], #104]\n\t"
+ "ldr r5, [%[m], #108]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #104]\n\t"
+ "str r7, [%[r], #108]\n\t"
+ "ldr r6, [%[r], #112]\n\t"
+ "ldr r7, [%[r], #116]\n\t"
+ "ldr r4, [%[m], #112]\n\t"
+ "ldr r5, [%[m], #116]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #112]\n\t"
+ "str r7, [%[r], #116]\n\t"
+ "ldr r6, [%[r], #120]\n\t"
+ "ldr r7, [%[r], #124]\n\t"
+ "ldr r4, [%[m], #120]\n\t"
+ "ldr r5, [%[m], #124]\n\t"
+ "and r4, r3\n\t"
+ "and r5, r3\n\t"
+ "sbc r6, r4\n\t"
+ "sbc r7, r5\n\t"
+ "str r6, [%[r], #120]\n\t"
+ "str r7, [%[r], #124]\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r3"
+ );
+}
+
+/* Subtract two Montgomery form numbers (r = a - b % m).
+ *
+ * r Result of subtration.
+ * a Number to subtract from in Montogmery form.
+ * b Number to subtract with in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[b], #56]\n\t"
+ "ldr r7, [%[b], #60]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[b], #72]\n\t"
+ "ldr r7, [%[b], #76]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[b], #88]\n\t"
+ "ldr r7, [%[b], #92]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[b], #104]\n\t"
+ "ldr r7, [%[b], #108]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[b], #120]\n\t"
+ "ldr r7, [%[b], #124]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "sbc %[b], %[b]\n\t"
+ "ldr r4, [%[r], #0]\n\t"
+ "ldr r5, [%[r], #4]\n\t"
+ "ldr r6, [%[m], #0]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "add r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[r], #8]\n\t"
+ "ldr r5, [%[r], #12]\n\t"
+ "ldr r6, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[r], #16]\n\t"
+ "ldr r5, [%[r], #20]\n\t"
+ "ldr r6, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[r], #24]\n\t"
+ "ldr r5, [%[r], #28]\n\t"
+ "ldr r6, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[r], #32]\n\t"
+ "ldr r5, [%[r], #36]\n\t"
+ "ldr r6, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[r], #40]\n\t"
+ "ldr r5, [%[r], #44]\n\t"
+ "ldr r6, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[r], #48]\n\t"
+ "ldr r5, [%[r], #52]\n\t"
+ "ldr r6, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[r], #56]\n\t"
+ "ldr r5, [%[r], #60]\n\t"
+ "ldr r6, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[r], #64]\n\t"
+ "ldr r5, [%[r], #68]\n\t"
+ "ldr r6, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[r], #72]\n\t"
+ "ldr r5, [%[r], #76]\n\t"
+ "ldr r6, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[r], #80]\n\t"
+ "ldr r5, [%[r], #84]\n\t"
+ "ldr r6, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[r], #88]\n\t"
+ "ldr r5, [%[r], #92]\n\t"
+ "ldr r6, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[r], #96]\n\t"
+ "ldr r5, [%[r], #100]\n\t"
+ "ldr r6, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[r], #104]\n\t"
+ "ldr r5, [%[r], #108]\n\t"
+ "ldr r6, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[r], #112]\n\t"
+ "ldr r5, [%[r], #116]\n\t"
+ "ldr r6, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[r], #120]\n\t"
+ "ldr r5, [%[r], #124]\n\t"
+ "ldr r6, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "mov r6, #0\n\t"
+ "adc %[b], r6\n\t"
+ "ldr r4, [%[r], #0]\n\t"
+ "ldr r5, [%[r], #4]\n\t"
+ "ldr r6, [%[m], #0]\n\t"
+ "ldr r7, [%[m], #4]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "add r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[r], #8]\n\t"
+ "ldr r5, [%[r], #12]\n\t"
+ "ldr r6, [%[m], #8]\n\t"
+ "ldr r7, [%[m], #12]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[r], #16]\n\t"
+ "ldr r5, [%[r], #20]\n\t"
+ "ldr r6, [%[m], #16]\n\t"
+ "ldr r7, [%[m], #20]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[r], #24]\n\t"
+ "ldr r5, [%[r], #28]\n\t"
+ "ldr r6, [%[m], #24]\n\t"
+ "ldr r7, [%[m], #28]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[r], #32]\n\t"
+ "ldr r5, [%[r], #36]\n\t"
+ "ldr r6, [%[m], #32]\n\t"
+ "ldr r7, [%[m], #36]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[r], #40]\n\t"
+ "ldr r5, [%[r], #44]\n\t"
+ "ldr r6, [%[m], #40]\n\t"
+ "ldr r7, [%[m], #44]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[r], #48]\n\t"
+ "ldr r5, [%[r], #52]\n\t"
+ "ldr r6, [%[m], #48]\n\t"
+ "ldr r7, [%[m], #52]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[r], #56]\n\t"
+ "ldr r5, [%[r], #60]\n\t"
+ "ldr r6, [%[m], #56]\n\t"
+ "ldr r7, [%[m], #60]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[r], #64]\n\t"
+ "ldr r5, [%[r], #68]\n\t"
+ "ldr r6, [%[m], #64]\n\t"
+ "ldr r7, [%[m], #68]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[r], #72]\n\t"
+ "ldr r5, [%[r], #76]\n\t"
+ "ldr r6, [%[m], #72]\n\t"
+ "ldr r7, [%[m], #76]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[r], #80]\n\t"
+ "ldr r5, [%[r], #84]\n\t"
+ "ldr r6, [%[m], #80]\n\t"
+ "ldr r7, [%[m], #84]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[r], #88]\n\t"
+ "ldr r5, [%[r], #92]\n\t"
+ "ldr r6, [%[m], #88]\n\t"
+ "ldr r7, [%[m], #92]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[r], #96]\n\t"
+ "ldr r5, [%[r], #100]\n\t"
+ "ldr r6, [%[m], #96]\n\t"
+ "ldr r7, [%[m], #100]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[r], #104]\n\t"
+ "ldr r5, [%[r], #108]\n\t"
+ "ldr r6, [%[m], #104]\n\t"
+ "ldr r7, [%[m], #108]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[r], #112]\n\t"
+ "ldr r5, [%[r], #116]\n\t"
+ "ldr r6, [%[m], #112]\n\t"
+ "ldr r7, [%[m], #116]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[r], #120]\n\t"
+ "ldr r5, [%[r], #124]\n\t"
+ "ldr r6, [%[m], #120]\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "and r6, %[b]\n\t"
+ "and r7, %[b]\n\t"
+ "adc r4, r6\n\t"
+ "adc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+}
+
+/* Conditionally add a and b using the mask m.
+ * m is -1 to add and 0 when not.
+ *
+ * r A single precision number representing conditional add result.
+ * a A single precision number to add with.
+ * b A single precision number to add.
+ * m Mask value to apply.
+ */
+SP_NOINLINE static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ sp_digit m)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r5, #128\n\t"
+ "mov r8, r5\n\t"
+ "mov r7, #0\n\t"
+ "1:\n\t"
+ "ldr r6, [%[b], r7]\n\t"
+ "and r6, %[m]\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, #1\n\t"
+ "add r5, %[c]\n\t"
+ "ldr r5, [%[a], r7]\n\t"
+ "adc r5, r6\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c]\n\t"
+ "str r5, [%[r], r7]\n\t"
+ "add r7, #4\n\t"
+ "cmp r7, r8\n\t"
+ "blt 1b\n\t"
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r5", "r6", "r7", "r8"
+ );
+
+ return c;
+}
+
+static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "ldr r2, [%[a]]\n\t"
+ "ldr r3, [%[a], #4]\n\t"
+ "lsr r2, r2, #1\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "str r2, [%[r], #0]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #12]\n\t"
+ "str r3, [%[r], #4]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "str r2, [%[r], #12]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #24]\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #28]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "str r2, [%[r], #24]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #36]\n\t"
+ "str r3, [%[r], #28]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #40]\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "str r2, [%[r], #36]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #48]\n\t"
+ "str r3, [%[r], #40]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #52]\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "str r2, [%[r], #48]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #60]\n\t"
+ "str r3, [%[r], #52]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #64]\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "str r2, [%[r], #60]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #72]\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #76]\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "str r2, [%[r], #72]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #84]\n\t"
+ "str r3, [%[r], #76]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #88]\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "str r2, [%[r], #84]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #96]\n\t"
+ "str r3, [%[r], #88]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #100]\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "str r2, [%[r], #96]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #108]\n\t"
+ "str r3, [%[r], #100]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #112]\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "str r2, [%[r], #108]\n\t"
+ "lsl r5, r4, #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "orr r3, r3, r5\n\t"
+ "ldr r2, [%[a], #120]\n\t"
+ "str r3, [%[r], #112]\n\t"
+ "lsl r5, r2, #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r4, r4, r5\n\t"
+ "ldr r3, [%[a], #124]\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "lsl r5, r3, #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "orr r2, r2, r5\n\t"
+ "str r2, [%[r], #120]\n\t"
+ "str r3, [%[r], #124]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5"
+ );
+}
+
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ sp_digit o;
+
+ o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1));
+ sp_1024_rshift1_32(r, r);
+ r[31] |= o << 31;
+}
+
+/* Double the Montgomery form projective point p.
+ *
+ * r Result of doubling point.
+ * p Point to double.
+ * t Temporary ordinate data.
+ */
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_dbl_32_ctx {
+ int state;
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_dbl_32_ctx;
+
+static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data;
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0:
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->x = r->x;
+ ctx->y = r->y;
+ ctx->z = r->z;
+
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+ ctx->state = 1;
+ break;
+ case 1:
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 2;
+ break;
+ case 2:
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 3;
+ break;
+ case 3:
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod);
+ ctx->state = 4;
+ break;
+ case 4:
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* T2 = T2/2 */
+ sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod);
+ ctx->state = 19;
+ /* fall-through */
+ case 19:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 19) {
+ err = FP_WOULDBLOCK;
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = r->x;
+ y = r->y;
+ z = r->z;
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(z, z, p1024_mod);
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod);
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod);
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(t1, t2, p1024_mod);
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(y, p->y, p1024_mod);
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod);
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod);
+ /* T2 = T2/2 */
+ sp_1024_div2_32(t2, t2, p1024_mod);
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod);
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod);
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(y, y, t2, p1024_mod);
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, #128\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "sub r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbc r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c]\n\t"
+ "add %[a], #4\n\t"
+ "add %[b], #4\n\t"
+ "add %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+ "bne 1b\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r7, [%[b], #4]\n\t"
+ "sub r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r7, [%[b], #12]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r7, [%[b], #20]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r7, [%[b], #28]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r7, [%[b], #36]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r7, [%[b], #44]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[b], #48]\n\t"
+ "ldr r7, [%[b], #52]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[b], #56]\n\t"
+ "ldr r7, [%[b], #60]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[b], #64]\n\t"
+ "ldr r7, [%[b], #68]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[b], #72]\n\t"
+ "ldr r7, [%[b], #76]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[b], #80]\n\t"
+ "ldr r7, [%[b], #84]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[b], #88]\n\t"
+ "ldr r7, [%[b], #92]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[b], #96]\n\t"
+ "ldr r7, [%[b], #100]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[b], #104]\n\t"
+ "ldr r7, [%[b], #108]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[b], #112]\n\t"
+ "ldr r7, [%[b], #116]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[b], #120]\n\t"
+ "ldr r7, [%[b], #124]\n\t"
+ "sbc r4, r6\n\t"
+ "sbc r5, r7\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "sbc %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r7"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Compare two numbers to determine if they are equal.
+ * Constant time implementation.
+ *
+ * a First number to compare.
+ * b Second number to compare.
+ * returns 1 when equal and 0 otherwise.
+ */
+static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b)
+{
+ return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
+ (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) |
+ (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
+ (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) |
+ (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) |
+ (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
+ (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) |
+ (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0;
+}
+
+/* Add two Montgomery form projective points.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_add_32_ctx {
+ int state;
+ sp_1024_proj_point_dbl_32_ctx dbl_ctx;
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* t3;
+ sp_digit* t4;
+ sp_digit* t5;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_add_32_ctx;
+
+static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0: /* INIT */
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->t3 = t + 4*32;
+ ctx->t4 = t + 6*32;
+ ctx->t5 = t + 8*32;
+
+ ctx->state = 1;
+ break;
+ case 1:
+ /* Check double */
+ (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y);
+ sp_1024_norm_32(ctx->t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0)
+ {
+ XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
+ ctx->state = 2;
+ }
+ else {
+ ctx->state = 3;
+ }
+ break;
+ case 2:
+ err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
+ if (err == MP_OKAY)
+ ctx->state = 27; /* done */
+ break;
+ case 3:
+ {
+ int i;
+ ctx->rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024));
+ ctx->x = ctx->rp[p->infinity | q->infinity]->x;
+ ctx->y = ctx->rp[p->infinity | q->infinity]->y;
+ ctx->z = ctx->rp[p->infinity | q->infinity]->z;
+
+ ctx->ap[0] = p;
+ ctx->ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ctx->ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ctx->ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ctx->ap[p->infinity]->z[i];
+ }
+ r->infinity = ctx->ap[p->infinity]->infinity;
+
+ ctx->state = 4;
+ break;
+ }
+ case 4:
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
+ ctx->state = 19;
+ break;
+ case 19:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 20;
+ break;
+ case 20:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod);
+ ctx->state = 21;
+ break;
+ case 21:
+ sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod);
+ ctx->state = 22;
+ break;
+ case 22:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod);
+ ctx->state = 23;
+ break;
+ case 23:
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 24;
+ break;
+ case 24:
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 25;
+ break;
+ case 25:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
+ ctx->state = 26;
+ break;
+ case 26:
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod);
+ ctx->state = 27;
+ /* fall-through */
+ case 27:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 27) {
+ err = FP_WOULDBLOCK;
+ }
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_add_32(sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod);
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(t4, t4, t3, p1024_mod);
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, x, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, y, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, y, t5, p1024_mod);
+ }
+}
+
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 1024 doubles.
+ * 268 adds.
+ *
+ * r Resulting point.
+ * g Point to multiply.
+ * k Scalar to multiply by.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
+ int map, int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td[16];
+ sp_point_1024 rtd;
+ sp_digit tmpd[2 * 32 * 5];
+#endif
+ sp_point_1024* t;
+ sp_point_1024* rt;
+ sp_digit* tmp;
+ sp_digit n;
+ int i;
+ int c;
+ int y;
+ int err;
+
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+#ifndef WC_NO_CACHE_RESISTANT
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 17, heap, DYNAMIC_TYPE_ECC);
+#else
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 16, heap, DYNAMIC_TYPE_ECC);
+#endif
+ if (t == NULL)
+ err = MEMORY_E;
+ tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (tmp == NULL)
+ err = MEMORY_E;
+#else
+ t = td;
+ tmp = tmpd;
+#endif
+
+ if (err == MP_OKAY) {
+ /* t[0] = {0, 0, 1} * norm */
+ XMEMSET(&t[0], 0, sizeof(t[0]));
+ t[0].infinity = 1;
+ /* t[1] = {g->x, g->y, g->z} * norm */
+ (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod);
+ t[1].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp);
+ t[ 2].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp);
+ t[ 3].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp);
+ t[ 4].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp);
+ t[ 5].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp);
+ t[ 6].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp);
+ t[ 7].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp);
+ t[ 8].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp);
+ t[ 9].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp);
+ t[10].infinity = 0;
+ sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp);
+ t[11].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp);
+ t[12].infinity = 0;
+ sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp);
+ t[13].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp);
+ t[14].infinity = 0;
+ sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp);
+ t[15].infinity = 0;
+
+ i = 30;
+ n = k[i+1] << 0;
+ c = 28;
+ y = (int)(n >> 28);
+ XMEMCPY(rt, &t[y], sizeof(sp_point_1024));
+ n <<= 4;
+ for (; i>=0 || c>=4; ) {
+ if (c < 4) {
+ n |= k[i--];
+ c += 32;
+ }
+ y = (n >> 28) & 0xf;
+ n <<= 4;
+ c -= 4;
+
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_add_32(rt, rt, &t[y], tmp);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, tmp);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (tmp != NULL) {
+ XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 32 * 5);
+ XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
+ }
+ if (t != NULL) {
+ XMEMSET(t, 0, sizeof(sp_point_1024) * 16);
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+ ForceZero(tmpd, sizeof(tmpd));
+ ForceZero(td, sizeof(td));
+#endif
+ sp_1024_point_free_32(rt, 1, heap);
+
+ return err;
+}
+
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Double the Montgomery form projective point p a number of times.
+ *
+ * r Result of repeated doubling of point.
+ * p Point to double.
+ * n Number of times to double
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n,
+ sp_digit* t)
+{
+ sp_digit* w = t;
+ sp_digit* a = t + 2*32;
+ sp_digit* b = t + 4*32;
+ sp_digit* t1 = t + 6*32;
+ sp_digit* t2 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = p->x;
+ y = p->y;
+ z = p->z;
+
+ /* Y = 2*Y */
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ /* W = Z^4 */
+ sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod);
+
+#ifndef WOLFSSL_SP_SMALL
+ while (--n > 0)
+#else
+ while (--n >= 0)
+#endif
+ {
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+#ifdef WOLFSSL_SP_SMALL
+ if (n != 0)
+#endif
+ {
+ /* W = W*Y^4 */
+ sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod);
+ }
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+ }
+#ifndef WOLFSSL_SP_SMALL
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+#endif
+ /* Y = Y/2 */
+ sp_1024_div2_32(y, y, p1024_mod);
+}
+
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* tmp = t + 4 * 32;
+
+ sp_1024_mont_inv_32(t1, a->z, tmp);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_1024 {
+ sp_digit x[32];
+ sp_digit y[32];
+} sp_table_entry_1024;
+
+#ifdef FP_ECC
+#endif /* FP_ECC */
+/* Add two Montgomery form projective points. The second point has a q value of
+ * one.
+ * Only the first point can be the same pointer as the result point.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p,
+ const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - X1 */
+ sp_1024_mont_sub_32(t2, t2, x, p1024_mod);
+ /* R = S2 - Y1 */
+ sp_1024_mont_sub_32(t4, t4, y, p1024_mod);
+ /* Z3 = H*Z1 */
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*X1*H^2 */
+ sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, t1, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, t3, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
+ sp_1024_mont_sub_32(t3, t3, x, p1024_mod);
+ sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, t3, t5, p1024_mod);
+ }
+}
+
+#ifdef WOLFSSL_SP_SMALL
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 256 bits between
+ *
+ * a The base point.
+ * table Place to store generated point data.
+ * tmp Temporary data.
+ * heap Heap to use for allocation.
+ */
+static int sp_1024_gen_stripe_table_32(const sp_point_1024* a,
+ sp_table_entry_1024* table, sp_digit* tmp, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td;
+ sp_point_1024 s1d;
+ sp_point_1024 s2d;
+#endif
+ sp_point_1024* t;
+ sp_point_1024* s1 = NULL;
+ sp_point_1024* s2 = NULL;
+ int i;
+ int j;
+ int err;
+
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, td, t);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s1d, s1);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s2d, s2);
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ t->infinity = 0;
+ sp_1024_proj_to_affine_32(t, tmp);
+
+ XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s1->infinity = 0;
+ XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s2->infinity = 0;
+
+ /* table[0] = {0, 0, infinity} */
+ XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
+ /* table[1] = Affine version of 'a' in Montgomery form */
+ XMEMCPY(table[1].x, t->x, sizeof(table->x));
+ XMEMCPY(table[1].y, t->y, sizeof(table->y));
+
+ for (i=1; i<4; i++) {
+ sp_1024_proj_point_dbl_n_32(t, 256, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[1<x, sizeof(table->x));
+ XMEMCPY(table[1<y, sizeof(table->y));
+ }
+
+ for (i=1; i<4; i++) {
+ XMEMCPY(s1->x, table[1<x));
+ XMEMCPY(s1->y, table[1<y));
+ for (j=(1<x, table[j-(1<x));
+ XMEMCPY(s2->y, table[j-(1<y));
+ sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[j].x, t->x, sizeof(table->x));
+ XMEMCPY(table[j].y, t->y, sizeof(table->y));
+ }
+ }
+ }
+
+ sp_1024_point_free_32(s2, 0, heap);
+ sp_1024_point_free_32(s1, 0, heap);
+ sp_1024_point_free_32( t, 0, heap);
+
+ return err;
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^256, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
+ * r Resulting point.
+ * k Scalar to multiply by.
+ * table Pre-computed table.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g,
+ const sp_table_entry_1024* table, const sp_digit* k, int map,
+ int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 rtd;
+ sp_point_1024 pd;
+ sp_digit td[2 * 32 * 5];
+#endif
+ sp_point_1024* rt;
+ sp_point_1024* p = NULL;
+ sp_digit* t;
+ int i;
+ int j;
+ int y;
+ int x;
+ int err;
+
+ (void)g;
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#else
+ t = td;
+#endif
+
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+
+ y = 0;
+ x = 255;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+ XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
+ rt->infinity = !y;
+ for (i=254; i>=0; i--) {
+ y = 0;
+ x = i;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+
+ sp_1024_proj_point_dbl_32(rt, rt, t);
+ XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
+ p->infinity = !y;
+ sp_1024_proj_point_add_qz1_32(rt, rt, p, t);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, t);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL) {
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(rt, 0, heap);
+
+ return err;
+}
+
+#ifdef FP_ECC
+#ifndef FP_ENTRIES
+ #define FP_ENTRIES 16
+#endif
+
+/* Cache entry - holds precomputation tables for a point. */
+typedef struct sp_cache_1024_t {
+ /* X ordinate of point that table was generated from. */
+ sp_digit x[32];
+ /* Y ordinate of point that table was generated from. */
+ sp_digit y[32];
+ /* Precomputation table for point. */
+ sp_table_entry_1024 table[16];
+ /* Count of entries in table. */
+ uint32_t cnt;
+ /* Point and table set in entry. */
+ int set;
+} sp_cache_1024_t;
+
+/* Cache of tables. */
+static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
+/* Index of last entry in cache. */
+static THREAD_LS_T int sp_cache_1024_last = -1;
+/* Cache has been initialized. */
+static THREAD_LS_T int sp_cache_1024_inited = 0;
+
+#ifndef HAVE_THREAD_LS
+ static volatile int initCacheMutex_1024 = 0;
+ static wolfSSL_Mutex sp_cache_1024_lock;
+#endif
+
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
+static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
+{
+ int i;
+ int j;
+ uint32_t least;
+
+ if (sp_cache_1024_inited == 0) {
+ for (i=0; i .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit qx_px[2 * 32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ qx_px = td + 8 * 32 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+
+ sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* h = t + 8 * 32;
+ sp_digit* r = t + 10 * 32;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_32(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_32(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_32(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_32(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_32(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_32(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 32;
+ sp_digit* pz2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* l = t + 8 * 32;
+ sp_digit* ty = t + 10 * 32;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_32(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_32(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_32(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* t2 = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_32(l, py, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_32(t2, t1, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_32(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* c = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_32(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_32(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_32(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 32;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_32(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_32(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 32 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_32(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_32(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_32(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, neg, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(neg, 1, NULL);
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_32(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
+ a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
+ a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = n-1; i >= 0; i--) {
+ r[j] |= (((sp_digit)a[i]) << s);
+ if (s >= 24U) {
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ r[++j] = (sp_digit)a[i] >> s;
+ s = 8U - s;
+ }
+ else {
+ s += 8U;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_32(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*32];
+ sp_digit t2d[2*32];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int32_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 32;
+ t2 = d + 2 * 32;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_32(t1, point->y);
+ (void)sp_1024_mod_32(t1, t1, p1024_mod);
+ sp_1024_sqr_32(t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ sp_1024_mul_32(t2, t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ (void)sp_1024_sub_32(t2, p1024_mod, t2);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_32(t1, p1024_mod);
+ sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(t1);
+ if (!sp_1024_iszero_32(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_32(pub, NULL);
+ }
+
+ sp_1024_point_free_32(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[32];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 32, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_32(pub->x) != 0) &&
+ (sp_1024_iszero_32(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_32(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) ||
+ (sp_1024_iszero_32(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_32(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_SP_ARM_THUMB_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c
index 6abd9a64f..890e1006f 100644
--- a/wolfcrypt/src/sp_c32.c
+++ b/wolfcrypt/src/sp_c32.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -75,7 +75,8 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 };
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -117,7 +118,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 23
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -151,7 +153,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -190,7 +194,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<89; i++) {
r[i+1] += r[i] >> 23;
@@ -1011,7 +1018,9 @@ SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[89]) * b[89];
@@ -1043,7 +1052,9 @@ SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[89]) * a[89];
@@ -1154,7 +1165,9 @@ SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[44]) * b[44];
@@ -1186,7 +1199,9 @@ SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[44]) * a[44];
@@ -1216,7 +1231,7 @@ SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -1225,7 +1240,8 @@ SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -1571,7 +1587,6 @@ static void sp_2048_mont_reduce_45(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_2048_mul_add_45(a+i, m, mu);
a[i+1] += a[i] >> 23;
a[i] &= 0x7fffff;
-
sp_2048_mont_shift_45(a, a);
sp_2048_cond_sub_45(a, a, m, 0 - (((a[44] >> 12) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -1587,8 +1602,8 @@ static void sp_2048_mont_reduce_45(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_45(r, a, b);
sp_2048_mont_reduce_45(r, m, mp);
@@ -1601,8 +1616,8 @@ static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_45(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_45(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_45(r, a);
sp_2048_mont_reduce_45(r, m, mp);
@@ -1702,26 +1717,8 @@ static void sp_2048_cond_add_45(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 45; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -1731,19 +1728,19 @@ SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<40; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff);
}
- r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff;
- r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff;
- r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff;
- r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff;
+ r[40] = (a[40] >> n) | ((a[41] << (23 - n)) & 0x7fffff);
+ r[41] = (a[41] >> n) | ((a[42] << (23 - n)) & 0x7fffff);
+ r[42] = (a[42] >> n) | ((a[43] << (23 - n)) & 0x7fffff);
+ r[43] = (a[43] >> n) | ((a[44] << (23 - n)) & 0x7fffff);
#endif
r[44] = a[44] >> n;
}
@@ -1752,7 +1749,9 @@ SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 23 bits from d1 and top 8 bits from d0. */
d = (d1 << 8) | (d0 >> 15);
@@ -1781,24 +1780,29 @@ static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_2048_div_45(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[90 + 1], t2d[45 + 1], sdd[45 + 1];
+ sp_digit t1d[90 + 1];
+ sp_digit t2d[45 + 1];
+ sp_digit sdd[45 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -1831,18 +1835,16 @@ static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_45(sd, d, 1L << 11);
sp_2048_mul_d_90(t1, a, 1L << 11);
dv = sd[44];
+ t1[45 + 45] += t1[45 + 45 - 1] >> 23;
+ t1[45 + 45 - 1] &= 0x7fffff;
for (i=45; i>=0; i--) {
- sp_digit hi;
- t1[45 + i] += t1[45 + i - 1] >> 23;
- t1[45 + i - 1] &= 0x7fffff;
- hi = t1[45 + i] - (t1[45 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[45 + i];
d1 <<= 23;
d1 += t1[45 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_2048_div_word_45(hi, t1[45 + i - 1], dv);
+ r1 = sp_2048_div_word_45(t1[45 + i], t1[45 + i - 1], dv);
#endif
sp_2048_mul_d_45(t2, sd, r1);
@@ -1863,7 +1865,7 @@ static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_45(t2, sd, r1);
sp_2048_sub_45(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 45U);
+ XMEMCPY(r, t1, sizeof(*r) * 90U);
for (i=0; i<44; i++) {
r[i+1] += r[i] >> 23;
r[i] &= 0x7fffff;
@@ -1919,7 +1921,8 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2010,7 +2013,8 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -2096,12 +2100,13 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 90) + 90];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2193,7 +2198,7 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 90);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (9 - c);
c += 23;
@@ -2228,7 +2233,7 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 2048 bits, just need to subtract.
@@ -2476,7 +2481,7 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_2048_norm_90(a + 90);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<89; i++) {
mu = (a[i] * mp) & 0x7fffff;
@@ -2510,7 +2515,6 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 23;
a[i] &= 0x7fffff;
#endif
-
sp_2048_mont_shift_90(a, a);
sp_2048_cond_sub_90(a, a, m, 0 - (((a[89] >> 1) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -2526,8 +2530,8 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_90(r, a, b);
sp_2048_mont_reduce_90(r, m, mp);
@@ -2540,8 +2544,8 @@ static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_90(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_90(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_90(r, a);
sp_2048_mont_reduce_90(r, m, mp);
@@ -2635,46 +2639,8 @@ static void sp_2048_cond_add_90(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 90; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 90; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -2684,16 +2650,16 @@ SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<88; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff);
}
- r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff;
+ r[88] = (a[88] >> n) | ((a[89] << (23 - n)) & 0x7fffff);
#endif
r[89] = a[89] >> n;
}
@@ -2702,7 +2668,9 @@ SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 23 bits from d1 and top 8 bits from d0. */
d = (d1 << 8) | (d0 >> 15);
@@ -2731,24 +2699,29 @@ static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_2048_div_90(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[180 + 1], t2d[90 + 1], sdd[90 + 1];
+ sp_digit t1d[180 + 1];
+ sp_digit t2d[90 + 1];
+ sp_digit sdd[90 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -2781,18 +2754,16 @@ static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_90(sd, d, 1L << 22);
sp_2048_mul_d_180(t1, a, 1L << 22);
dv = sd[89];
+ t1[90 + 90] += t1[90 + 90 - 1] >> 23;
+ t1[90 + 90 - 1] &= 0x7fffff;
for (i=90; i>=0; i--) {
- sp_digit hi;
- t1[90 + i] += t1[90 + i - 1] >> 23;
- t1[90 + i - 1] &= 0x7fffff;
- hi = t1[90 + i] - (t1[90 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[90 + i];
d1 <<= 23;
d1 += t1[90 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_2048_div_word_90(hi, t1[90 + i - 1], dv);
+ r1 = sp_2048_div_word_90(t1[90 + i], t1[90 + i - 1], dv);
#endif
sp_2048_mul_d_90(t2, sd, r1);
@@ -2813,7 +2784,7 @@ static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_90(t2, sd, r1);
sp_2048_sub_90(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 90U);
+ XMEMCPY(r, t1, sizeof(*r) * 180U);
for (i=0; i<89; i++) {
r[i+1] += r[i] >> 23;
r[i] &= 0x7fffff;
@@ -2871,7 +2842,8 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2962,7 +2934,8 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -3048,12 +3021,13 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 180) + 180];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3145,7 +3119,7 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 180);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (9 - c);
c += 23;
@@ -3179,7 +3153,7 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -3195,15 +3169,15 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -3296,13 +3270,15 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[180], md[90], rd[180];
+ sp_digit ad[180];
+ sp_digit md[90];
+ sp_digit rd[180];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -3420,7 +3396,7 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -3438,9 +3414,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3503,7 +3479,9 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[180], d[90], m[90];
+ sp_digit a[180];
+ sp_digit d[90];
+ sp_digit m[90];
sp_digit* r = a;
int err = MP_OKAY;
@@ -3546,19 +3524,19 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 90);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -3633,8 +3611,13 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[90 * 2];
- sp_digit p[45], q[45], dp[45], dq[45], qi[45];
- sp_digit tmpa[90], tmpb[90];
+ sp_digit p[45];
+ sp_digit q[45];
+ sp_digit dp[45];
+ sp_digit dq[45];
+ sp_digit qi[45];
+ sp_digit tmpa[90];
+ sp_digit tmpb[90];
sp_digit* r = a;
int err = MP_OKAY;
@@ -3696,8 +3679,8 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -3720,17 +3703,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 90;
mp_clamp(r);
#elif DIGIT_BIT < 23
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 90; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 23) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -3743,14 +3728,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 90; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 23 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -3777,7 +3764,8 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -3833,7 +3821,9 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[180], ed[90], md[90];
+ sp_digit bd[180];
+ sp_digit ed[90];
+ sp_digit md[90];
#else
sp_digit* d = NULL;
#endif
@@ -3905,7 +3895,8 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_2048
-SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -3915,7 +3906,8 @@ SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[89];
r[90] = s >> (23U - n);
@@ -4119,9 +4111,11 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4166,7 +4160,7 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const
n <<= 4;
c -= 4;
sp_2048_lshift_90(r, norm, (byte)y);
- for (; i>=0 || c>=4; ) {
+ while ((i >= 0) || (c >= 4)) {
if (c < 4) {
n |= e[i--] << (9 - c);
c += 23;
@@ -4220,8 +4214,8 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -4288,7 +4282,9 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[180], ed[90], md[90];
+ sp_digit bd[180];
+ sp_digit ed[90];
+ sp_digit md[90];
#else
sp_digit* d = NULL;
#endif
@@ -4353,6 +4349,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -4381,7 +4378,8 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -4438,7 +4436,9 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[90], ed[45], md[45];
+ sp_digit bd[90];
+ sp_digit ed[45];
+ sp_digit md[45];
#else
sp_digit* d = NULL;
#endif
@@ -4508,7 +4508,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#endif
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -4522,7 +4522,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -4564,7 +4565,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 23
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -4598,7 +4600,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -4637,7 +4641,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<133; i++) {
r[i+1] += r[i] >> 23;
@@ -4680,7 +4687,8 @@ static void sp_3072_to_bin(sp_digit* r, byte* a)
SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j;
+ int i;
+ int j;
int64_t t[134];
XMEMSET(t, 0, sizeof(t));
@@ -4703,7 +4711,8 @@ SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a)
{
- int i, j;
+ int i;
+ int j;
int64_t t[134];
XMEMSET(t, 0, sizeof(t));
@@ -4904,7 +4913,9 @@ SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[133]) * b[133];
@@ -4936,7 +4947,9 @@ SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[133]) * a[133];
@@ -5045,7 +5058,9 @@ SP_NOINLINE static int sp_3072_sub_67(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[66]) * b[66];
@@ -5077,7 +5092,9 @@ SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[66]) * a[66];
@@ -5107,7 +5124,7 @@ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -5116,7 +5133,8 @@ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -5390,7 +5408,8 @@ static void sp_3072_mont_shift_67(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
s = a[67];
n = a[66] >> 18;
@@ -5403,7 +5422,8 @@ static void sp_3072_mont_shift_67(sp_digit* r, const sp_digit* a)
n += s << 5;
r[66] = n;
#else
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
int i;
s = a[67]; n = a[66] >> 18;
@@ -5456,7 +5476,6 @@ static void sp_3072_mont_reduce_67(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_3072_mul_add_67(a+i, m, mu);
a[i+1] += a[i] >> 23;
a[i] &= 0x7fffff;
-
sp_3072_mont_shift_67(a, a);
sp_3072_cond_sub_67(a, a, m, 0 - (((a[66] >> 18) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -5472,8 +5491,8 @@ static void sp_3072_mont_reduce_67(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_67(r, a, b);
sp_3072_mont_reduce_67(r, m, mp);
@@ -5486,8 +5505,8 @@ static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_67(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_67(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_67(r, a);
sp_3072_mont_reduce_67(r, m, mp);
@@ -5591,30 +5610,13 @@ static void sp_3072_cond_add_67(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 67; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
#ifdef WOLFSSL_SP_DIV_32
static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 23 bits from d1 and top 8 bits from d0. */
d = (d1 << 8) | (d0 >> 15);
@@ -5643,24 +5645,28 @@ static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Large number of bits in last word.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_3072_div_67(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[134], t2d[67 + 1];
+ sp_digit t1d[134];
+ sp_digit t2d[67 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -5688,17 +5694,15 @@ static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m,
dv = d[66];
XMEMCPY(t1, a, sizeof(*t1) * 2U * 67U);
for (i=66; i>=0; i--) {
- sp_digit hi;
t1[67 + i] += t1[67 + i - 1] >> 23;
t1[67 + i - 1] &= 0x7fffff;
- hi = t1[67 + i] - (t1[67 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[67 + i];
d1 <<= 23;
d1 += t1[67 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_3072_div_word_67(hi, t1[67 + i - 1], dv);
+ r1 = sp_3072_div_word_67(t1[67 + i], t1[67 + i - 1], dv);
#endif
sp_3072_mul_d_67(t2, d, r1);
@@ -5719,7 +5723,7 @@ static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_3072_mul_d_67(t2, d, r1);
(void)sp_3072_sub_67(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 67U);
+ XMEMCPY(r, t1, sizeof(*r) * 134U);
for (i=0; i<66; i++) {
r[i+1] += r[i] >> 23;
r[i] &= 0x7fffff;
@@ -5772,7 +5776,8 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5863,7 +5868,8 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -5949,12 +5955,13 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 134) + 134];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6046,7 +6053,7 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 134);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (9 - c);
c += 23;
@@ -6081,7 +6088,7 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 3072 bits, just need to subtract.
@@ -6353,7 +6360,7 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_3072_norm_134(a + 134);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<133; i++) {
mu = (a[i] * mp) & 0x7fffff;
@@ -6387,7 +6394,6 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 23;
a[i] &= 0x7fffff;
#endif
-
sp_3072_mont_shift_134(a, a);
sp_3072_cond_sub_134(a, a, m, 0 - (((a[133] >> 13) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -6403,8 +6409,8 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_134(r, a, b);
sp_3072_mont_reduce_134(r, m, mp);
@@ -6417,8 +6423,8 @@ static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_134(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_134(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_134(r, a);
sp_3072_mont_reduce_134(r, m, mp);
@@ -6516,46 +6522,8 @@ static void sp_3072_cond_add_134(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 134; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 134; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -6565,20 +6533,20 @@ SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<128; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff);
}
- r[128] = ((a[128] >> n) | (a[129] << (23 - n))) & 0x7fffff;
- r[129] = ((a[129] >> n) | (a[130] << (23 - n))) & 0x7fffff;
- r[130] = ((a[130] >> n) | (a[131] << (23 - n))) & 0x7fffff;
- r[131] = ((a[131] >> n) | (a[132] << (23 - n))) & 0x7fffff;
- r[132] = ((a[132] >> n) | (a[133] << (23 - n))) & 0x7fffff;
+ r[128] = (a[128] >> n) | ((a[129] << (23 - n)) & 0x7fffff);
+ r[129] = (a[129] >> n) | ((a[130] << (23 - n)) & 0x7fffff);
+ r[130] = (a[130] >> n) | ((a[131] << (23 - n)) & 0x7fffff);
+ r[131] = (a[131] >> n) | ((a[132] << (23 - n)) & 0x7fffff);
+ r[132] = (a[132] >> n) | ((a[133] << (23 - n)) & 0x7fffff);
#endif
r[133] = a[133] >> n;
}
@@ -6587,7 +6555,9 @@ SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 23 bits from d1 and top 8 bits from d0. */
d = (d1 << 8) | (d0 >> 15);
@@ -6616,24 +6586,29 @@ static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_3072_div_134(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[268 + 1], t2d[134 + 1], sdd[134 + 1];
+ sp_digit t1d[268 + 1];
+ sp_digit t2d[134 + 1];
+ sp_digit sdd[134 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -6666,18 +6641,16 @@ static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_3072_mul_d_134(sd, d, 1L << 10);
sp_3072_mul_d_268(t1, a, 1L << 10);
dv = sd[133];
+ t1[134 + 134] += t1[134 + 134 - 1] >> 23;
+ t1[134 + 134 - 1] &= 0x7fffff;
for (i=134; i>=0; i--) {
- sp_digit hi;
- t1[134 + i] += t1[134 + i - 1] >> 23;
- t1[134 + i - 1] &= 0x7fffff;
- hi = t1[134 + i] - (t1[134 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[134 + i];
d1 <<= 23;
d1 += t1[134 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_3072_div_word_134(hi, t1[134 + i - 1], dv);
+ r1 = sp_3072_div_word_134(t1[134 + i], t1[134 + i - 1], dv);
#endif
sp_3072_mul_d_134(t2, sd, r1);
@@ -6698,7 +6671,7 @@ static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_3072_mul_d_134(t2, sd, r1);
sp_3072_sub_134(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 134U);
+ XMEMCPY(r, t1, sizeof(*r) * 268U);
for (i=0; i<133; i++) {
r[i+1] += r[i] >> 23;
r[i] &= 0x7fffff;
@@ -6756,7 +6729,8 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6847,7 +6821,8 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -6933,12 +6908,13 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit td[(32 * 268) + 268];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7030,7 +7006,7 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 268);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (9 - c);
c += 23;
@@ -7064,7 +7040,7 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -7080,15 +7056,15 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -7181,13 +7157,15 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[268], md[134], rd[268];
+ sp_digit ad[268];
+ sp_digit md[134];
+ sp_digit rd[268];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -7305,7 +7283,7 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -7323,9 +7301,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7388,7 +7366,9 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[268], d[134], m[134];
+ sp_digit a[268];
+ sp_digit d[134];
+ sp_digit m[134];
sp_digit* r = a;
int err = MP_OKAY;
@@ -7431,19 +7411,19 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 134);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -7518,8 +7498,13 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[134 * 2];
- sp_digit p[67], q[67], dp[67], dq[67], qi[67];
- sp_digit tmpa[134], tmpb[134];
+ sp_digit p[67];
+ sp_digit q[67];
+ sp_digit dp[67];
+ sp_digit dq[67];
+ sp_digit qi[67];
+ sp_digit tmpa[134];
+ sp_digit tmpb[134];
sp_digit* r = a;
int err = MP_OKAY;
@@ -7581,8 +7566,8 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -7605,17 +7590,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 134;
mp_clamp(r);
#elif DIGIT_BIT < 23
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 134; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 23) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -7628,14 +7615,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 134; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 23 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -7662,7 +7651,8 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -7718,7 +7708,9 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[268], ed[134], md[134];
+ sp_digit bd[268];
+ sp_digit ed[134];
+ sp_digit md[134];
#else
sp_digit* d = NULL;
#endif
@@ -7790,7 +7782,8 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_3072
-SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -7800,7 +7793,8 @@ SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[133];
r[134] = s >> (23U - n);
@@ -8092,9 +8086,11 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -8139,7 +8135,7 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const
n <<= 4;
c -= 4;
sp_3072_lshift_134(r, norm, (byte)y);
- for (; i>=0 || c>=4; ) {
+ while ((i >= 0) || (c >= 4)) {
if (c < 4) {
n |= e[i--] << (9 - c);
c += 23;
@@ -8193,8 +8189,8 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -8261,7 +8257,9 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[268], ed[134], md[134];
+ sp_digit bd[268];
+ sp_digit ed[134];
+ sp_digit md[134];
#else
sp_digit* d = NULL;
#endif
@@ -8326,6 +8324,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -8354,7 +8353,8 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -8411,7 +8411,9 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[134], ed[67], md[67];
+ sp_digit bd[134];
+ sp_digit ed[67];
+ sp_digit md[67];
#else
sp_digit* d = NULL;
#endif
@@ -8481,7 +8483,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#endif
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -8495,7 +8497,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8537,7 +8540,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 21
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8571,7 +8575,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -8610,7 +8616,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<195; i++) {
r[i+1] += r[i] >> 21;
@@ -8653,7 +8662,8 @@ static void sp_4096_to_bin(sp_digit* r, byte* a)
SP_NOINLINE static void sp_4096_mul_49(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j;
+ int i;
+ int j;
int64_t t[98];
XMEMSET(t, 0, sizeof(t));
@@ -8676,7 +8686,8 @@ SP_NOINLINE static void sp_4096_mul_49(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_4096_sqr_49(sp_digit* r, const sp_digit* a)
{
- int i, j;
+ int i;
+ int j;
int64_t t[98];
XMEMSET(t, 0, sizeof(t));
@@ -8969,7 +8980,9 @@ SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[195]) * b[195];
@@ -9001,7 +9014,9 @@ SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_4096_sqr_196(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[195]) * a[195];
@@ -9082,7 +9097,9 @@ SP_NOINLINE static int sp_4096_sub_98(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_4096_mul_98(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[97]) * b[97];
@@ -9114,7 +9131,9 @@ SP_NOINLINE static void sp_4096_mul_98(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[97]) * a[97];
@@ -9144,8 +9163,8 @@ SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */
-#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
+#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
+#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -9154,7 +9173,8 @@ SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -9477,7 +9497,6 @@ static void sp_4096_mont_reduce_98(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_4096_mul_add_98(a+i, m, mu);
a[i+1] += a[i] >> 21;
a[i] &= 0x1fffff;
-
sp_4096_mont_shift_98(a, a);
sp_4096_cond_sub_98(a, a, m, 0 - (((a[97] >> 11) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -9493,8 +9512,8 @@ static void sp_4096_mont_reduce_98(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_98(r, a, b);
sp_4096_mont_reduce_98(r, m, mp);
@@ -9507,8 +9526,8 @@ static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_98(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_98(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_98(r, a);
sp_4096_mont_reduce_98(r, m, mp);
@@ -9608,46 +9627,8 @@ static void sp_4096_cond_add_98(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_sub_98(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 98; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_add_98(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 98; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -9657,16 +9638,16 @@ SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<96; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (21 - n)) & 0x1fffff);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (21 - n)) & 0x1fffff);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (21 - n)) & 0x1fffff);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (21 - n)) & 0x1fffff);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (21 - n)) & 0x1fffff);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (21 - n)) & 0x1fffff);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (21 - n)) & 0x1fffff);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (21 - n)) & 0x1fffff);
}
- r[96] = ((a[96] >> n) | (a[97] << (21 - n))) & 0x1fffff;
+ r[96] = (a[96] >> n) | ((a[97] << (21 - n)) & 0x1fffff);
#endif
r[97] = a[97] >> n;
}
@@ -9675,7 +9656,9 @@ SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 21 bits from d1 and top 10 bits from d0. */
d = (d1 << 10) | (d0 >> 11);
@@ -9704,24 +9687,29 @@ static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_4096_div_98(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[196 + 1], t2d[98 + 1], sdd[98 + 1];
+ sp_digit t1d[196 + 1];
+ sp_digit t2d[98 + 1];
+ sp_digit sdd[98 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -9754,18 +9742,16 @@ static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_98(sd, d, 1L << 10);
sp_4096_mul_d_196(t1, a, 1L << 10);
dv = sd[97];
+ t1[98 + 98] += t1[98 + 98 - 1] >> 21;
+ t1[98 + 98 - 1] &= 0x1fffff;
for (i=98; i>=0; i--) {
- sp_digit hi;
- t1[98 + i] += t1[98 + i - 1] >> 21;
- t1[98 + i - 1] &= 0x1fffff;
- hi = t1[98 + i] - (t1[98 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[98 + i];
d1 <<= 21;
d1 += t1[98 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_4096_div_word_98(hi, t1[98 + i - 1], dv);
+ r1 = sp_4096_div_word_98(t1[98 + i], t1[98 + i - 1], dv);
#endif
sp_4096_mul_d_98(t2, sd, r1);
@@ -9786,7 +9772,7 @@ static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_98(t2, sd, r1);
sp_4096_sub_98(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 98U);
+ XMEMCPY(r, t1, sizeof(*r) * 196U);
for (i=0; i<97; i++) {
r[i+1] += r[i] >> 21;
r[i] &= 0x1fffff;
@@ -9842,7 +9828,8 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -9933,7 +9920,8 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -10019,12 +10007,13 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 196) + 196];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10116,7 +10105,7 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 196);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (11 - c);
c += 21;
@@ -10151,8 +10140,8 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */
-#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
+#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
+#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 4096 bits, just need to subtract.
@@ -10412,7 +10401,7 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_4096_norm_196(a + 196);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<195; i++) {
mu = (a[i] * mp) & 0x1fffff;
@@ -10446,7 +10435,6 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 21;
a[i] &= 0x1fffff;
#endif
-
sp_4096_mont_shift_196(a, a);
sp_4096_cond_sub_196(a, a, m, 0 - (((a[195] >> 1) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -10462,8 +10450,8 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_196(r, a, b);
sp_4096_mont_reduce_196(r, m, mp);
@@ -10476,8 +10464,8 @@ static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_196(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_196(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_196(r, a);
sp_4096_mont_reduce_196(r, m, mp);
@@ -10573,46 +10561,8 @@ static void sp_4096_cond_add_196(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 196; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_add_196(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 196; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -10622,18 +10572,18 @@ SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<192; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (21 - n)) & 0x1fffff);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (21 - n)) & 0x1fffff);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (21 - n)) & 0x1fffff);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (21 - n)) & 0x1fffff);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (21 - n)) & 0x1fffff);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (21 - n)) & 0x1fffff);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (21 - n)) & 0x1fffff);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (21 - n)) & 0x1fffff);
}
- r[192] = ((a[192] >> n) | (a[193] << (21 - n))) & 0x1fffff;
- r[193] = ((a[193] >> n) | (a[194] << (21 - n))) & 0x1fffff;
- r[194] = ((a[194] >> n) | (a[195] << (21 - n))) & 0x1fffff;
+ r[192] = (a[192] >> n) | ((a[193] << (21 - n)) & 0x1fffff);
+ r[193] = (a[193] >> n) | ((a[194] << (21 - n)) & 0x1fffff);
+ r[194] = (a[194] >> n) | ((a[195] << (21 - n)) & 0x1fffff);
#endif
r[195] = a[195] >> n;
}
@@ -10642,7 +10592,9 @@ SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 21 bits from d1 and top 10 bits from d0. */
d = (d1 << 10) | (d0 >> 11);
@@ -10671,24 +10623,29 @@ static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_4096_div_196(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_32
int64_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[392 + 1], t2d[196 + 1], sdd[196 + 1];
+ sp_digit t1d[392 + 1];
+ sp_digit t2d[196 + 1];
+ sp_digit sdd[196 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -10721,18 +10678,16 @@ static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_196(sd, d, 1L << 20);
sp_4096_mul_d_392(t1, a, 1L << 20);
dv = sd[195];
+ t1[196 + 196] += t1[196 + 196 - 1] >> 21;
+ t1[196 + 196 - 1] &= 0x1fffff;
for (i=196; i>=0; i--) {
- sp_digit hi;
- t1[196 + i] += t1[196 + i - 1] >> 21;
- t1[196 + i - 1] &= 0x1fffff;
- hi = t1[196 + i] - (t1[196 + i] == dv);
#ifndef WOLFSSL_SP_DIV_32
- d1 = hi;
+ d1 = t1[196 + i];
d1 <<= 21;
d1 += t1[196 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_4096_div_word_196(hi, t1[196 + i - 1], dv);
+ r1 = sp_4096_div_word_196(t1[196 + i], t1[196 + i - 1], dv);
#endif
sp_4096_mul_d_196(t2, sd, r1);
@@ -10753,7 +10708,7 @@ static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_196(t2, sd, r1);
sp_4096_sub_196(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 196U);
+ XMEMCPY(r, t1, sizeof(*r) * 392U);
for (i=0; i<195; i++) {
r[i+1] += r[i] >> 21;
r[i] &= 0x1fffff;
@@ -10811,7 +10766,8 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10902,7 +10858,8 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -10988,12 +10945,13 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit td[(32 * 392) + 392];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11085,7 +11043,7 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 392);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (11 - c);
c += 21;
@@ -11119,7 +11077,7 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -11135,15 +11093,15 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -11236,13 +11194,15 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[392], md[196], rd[392];
+ sp_digit ad[392];
+ sp_digit md[196];
+ sp_digit rd[392];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -11360,7 +11320,7 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -11378,9 +11338,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11443,7 +11403,9 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[392], d[196], m[196];
+ sp_digit a[392];
+ sp_digit d[196];
+ sp_digit m[196];
sp_digit* r = a;
int err = MP_OKAY;
@@ -11486,19 +11448,19 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 196);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -11573,8 +11535,13 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[196 * 2];
- sp_digit p[98], q[98], dp[98], dq[98], qi[98];
- sp_digit tmpa[196], tmpb[196];
+ sp_digit p[98];
+ sp_digit q[98];
+ sp_digit dp[98];
+ sp_digit dq[98];
+ sp_digit qi[98];
+ sp_digit tmpa[196];
+ sp_digit tmpb[196];
sp_digit* r = a;
int err = MP_OKAY;
@@ -11636,8 +11603,8 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -11660,17 +11627,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 196;
mp_clamp(r);
#elif DIGIT_BIT < 21
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 196; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 21) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -11683,14 +11652,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 196; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 21 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -11717,7 +11688,8 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -11773,7 +11745,9 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[392], ed[196], md[196];
+ sp_digit bd[392];
+ sp_digit ed[196];
+ sp_digit md[196];
#else
sp_digit* d = NULL;
#endif
@@ -11845,7 +11819,8 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_4096
-SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -11855,7 +11830,8 @@ SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (21 - n))) & 0x1fffff;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[195];
r[196] = s >> (21U - n);
@@ -12271,9 +12247,11 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12318,7 +12296,7 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const
n <<= 4;
c -= 4;
sp_4096_lshift_196(r, norm, (byte)y);
- for (; i>=0 || c>=4; ) {
+ while ((i >= 0) || (c >= 4)) {
if (c < 4) {
n |= e[i--] << (11 - c);
c += 21;
@@ -12372,8 +12350,8 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -12440,7 +12418,9 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[392], ed[196], md[196];
+ sp_digit bd[392];
+ sp_digit ed[196];
+ sp_digit md[196];
#else
sp_digit* d = NULL;
#endif
@@ -12505,6 +12485,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -12524,19 +12505,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 10];
+ /* Y ordinate of point. */
sp_digit y[2 * 10];
+ /* Z ordinate of point. */
sp_digit z[2 * 10];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -12606,370 +12591,6 @@ static const sp_digit p256_b[10] = {
};
#endif
-static int sp_256_point_new_ex_10(void* heap, sp_point_256* sp, sp_point_256** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), &(sp), &(p))
-#endif
-
-
-static void sp_256_point_free_10(sp_point_256* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- int64_t* td;
-#else
- int64_t td[8];
- int64_t a32d[8];
-#endif
- int64_t* t;
- int64_t* a32;
- int64_t o;
- int err = MP_OKAY;
-
- (void)m;
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
- if (td == NULL) {
- return MEMORY_E;
- }
-#endif
-
- if (err == MP_OKAY) {
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- t = td;
- a32 = td + 8;
-#else
- t = td;
- a32 = a32d;
-#endif
-
- a32[0] = a[0];
- a32[0] |= a[1] << 26U;
- a32[0] &= 0xffffffffL;
- a32[1] = (sp_digit)(a[1] >> 6);
- a32[1] |= a[2] << 20U;
- a32[1] &= 0xffffffffL;
- a32[2] = (sp_digit)(a[2] >> 12);
- a32[2] |= a[3] << 14U;
- a32[2] &= 0xffffffffL;
- a32[3] = (sp_digit)(a[3] >> 18);
- a32[3] |= a[4] << 8U;
- a32[3] &= 0xffffffffL;
- a32[4] = (sp_digit)(a[4] >> 24);
- a32[4] |= a[5] << 2U;
- a32[4] |= a[6] << 28U;
- a32[4] &= 0xffffffffL;
- a32[5] = (sp_digit)(a[6] >> 4);
- a32[5] |= a[7] << 22U;
- a32[5] &= 0xffffffffL;
- a32[6] = (sp_digit)(a[7] >> 10);
- a32[6] |= a[8] << 16U;
- a32[6] &= 0xffffffffL;
- a32[7] = (sp_digit)(a[8] >> 16);
- a32[7] |= a[9] << 10U;
- a32[7] &= 0xffffffffL;
-
- /* 1 1 0 -1 -1 -1 -1 0 */
- t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
- /* 0 1 1 0 -1 -1 -1 -1 */
- t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
- /* 0 0 1 1 0 -1 -1 -1 */
- t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
- /* -1 -1 0 2 2 1 0 -1 */
- t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
- /* 0 -1 -1 0 2 2 1 0 */
- t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
- /* 0 0 -1 -1 0 2 2 1 */
- t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
- /* -1 -1 0 0 0 1 3 2 */
- t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
- /* 1 0 -1 -1 -1 -1 0 3 */
- t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
- t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
- t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
- t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
- t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
- t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
- t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
- t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
- o = t[7] >> 32U; t[7] &= 0xffffffffL;
- t[0] += o;
- t[3] -= o;
- t[6] -= o;
- t[7] += o;
- t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
- t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
- t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
- t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
- t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
- t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
- t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
-
- r[0] = (sp_digit)(t[0]) & 0x3ffffffL;
- r[1] = (sp_digit)(t[0] >> 26U);
- r[1] |= (sp_digit)(t[1] << 6U);
- r[1] &= 0x3ffffffL;
- r[2] = (sp_digit)(t[1] >> 20U);
- r[2] |= (sp_digit)(t[2] << 12U);
- r[2] &= 0x3ffffffL;
- r[3] = (sp_digit)(t[2] >> 14U);
- r[3] |= (sp_digit)(t[3] << 18U);
- r[3] &= 0x3ffffffL;
- r[4] = (sp_digit)(t[3] >> 8U);
- r[4] |= (sp_digit)(t[4] << 24U);
- r[4] &= 0x3ffffffL;
- r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL;
- r[6] = (sp_digit)(t[4] >> 28U);
- r[6] |= (sp_digit)(t[5] << 4U);
- r[6] &= 0x3ffffffL;
- r[7] = (sp_digit)(t[5] >> 22U);
- r[7] |= (sp_digit)(t[6] << 10U);
- r[7] &= 0x3ffffffL;
- r[8] = (sp_digit)(t[6] >> 16U);
- r[8] |= (sp_digit)(t[7] << 16U);
- r[8] &= 0x3ffffffL;
- r[9] = (sp_digit)(t[7] >> 10U);
- }
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_ECC);
- }
-#endif
-
- return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 26
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 26
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0x3ffffff;
- s = 26U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 26U) <= (word32)DIGIT_BIT) {
- s += 26U;
- r[j] &= 0x3ffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 26) {
- r[j] &= 0x3ffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 26 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_256.
- *
- * p Point of type sp_point_256 (result).
- * pm Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_10(sp_point_256* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_256_from_mp(p->x, 10, pm->x);
- sp_256_from_mp(p->y, 10, pm->y);
- sp_256_from_mp(p->z, 10, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_256_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 26
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 10);
- r->used = 10;
- mp_clamp(r);
-#elif DIGIT_BIT < 26
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 10; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 26) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 26 - s;
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 10; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 26 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 26 - s;
- }
- else {
- s += 26;
- }
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_256 to type ecc_point.
- *
- * p Point of type sp_point_256.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm)
-{
- int err;
-
- err = sp_256_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
#ifdef WOLFSSL_SP_SMALL
/* Multiply a and b into r. (r = a * b)
*
@@ -12980,7 +12601,9 @@ static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm)
SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int64_t c;
c = ((int64_t)a[9]) * b[9];
@@ -13139,6 +12762,469 @@ SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a,
}
#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
+{
+ int i;
+ int j;
+ int k;
+ int64_t c;
+
+ c = ((int64_t)a[9]) * a[9];
+ r[19] = (sp_digit)(c >> 26);
+ c = (c & 0x3ffffff) << 26;
+ for (k = 17; k >= 0; k--) {
+ for (i = 9; i >= 0; i--) {
+ j = k - i;
+ if (j >= 10 || i <= j) {
+ break;
+ }
+ if (j < 0) {
+ continue;
+ }
+
+ c += ((int64_t)a[i]) * a[j] * 2;
+ }
+ if (i == j) {
+ c += ((int64_t)a[i]) * a[i];
+ }
+
+ r[k + 2] += (sp_digit)(c >> 52);
+ r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff);
+ c = (c & 0x3ffffff) << 26;
+ }
+ r[0] = (sp_digit)(c >> 26);
+}
+
+#else
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
+{
+ int64_t t0 = ((int64_t)a[ 0]) * a[ 0];
+ int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2;
+ int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2
+ + ((int64_t)a[ 1]) * a[ 1];
+ int64_t t3 = (((int64_t)a[ 0]) * a[ 3]
+ + ((int64_t)a[ 1]) * a[ 2]) * 2;
+ int64_t t4 = (((int64_t)a[ 0]) * a[ 4]
+ + ((int64_t)a[ 1]) * a[ 3]) * 2
+ + ((int64_t)a[ 2]) * a[ 2];
+ int64_t t5 = (((int64_t)a[ 0]) * a[ 5]
+ + ((int64_t)a[ 1]) * a[ 4]
+ + ((int64_t)a[ 2]) * a[ 3]) * 2;
+ int64_t t6 = (((int64_t)a[ 0]) * a[ 6]
+ + ((int64_t)a[ 1]) * a[ 5]
+ + ((int64_t)a[ 2]) * a[ 4]) * 2
+ + ((int64_t)a[ 3]) * a[ 3];
+ int64_t t7 = (((int64_t)a[ 0]) * a[ 7]
+ + ((int64_t)a[ 1]) * a[ 6]
+ + ((int64_t)a[ 2]) * a[ 5]
+ + ((int64_t)a[ 3]) * a[ 4]) * 2;
+ int64_t t8 = (((int64_t)a[ 0]) * a[ 8]
+ + ((int64_t)a[ 1]) * a[ 7]
+ + ((int64_t)a[ 2]) * a[ 6]
+ + ((int64_t)a[ 3]) * a[ 5]) * 2
+ + ((int64_t)a[ 4]) * a[ 4];
+ int64_t t9 = (((int64_t)a[ 0]) * a[ 9]
+ + ((int64_t)a[ 1]) * a[ 8]
+ + ((int64_t)a[ 2]) * a[ 7]
+ + ((int64_t)a[ 3]) * a[ 6]
+ + ((int64_t)a[ 4]) * a[ 5]) * 2;
+ int64_t t10 = (((int64_t)a[ 1]) * a[ 9]
+ + ((int64_t)a[ 2]) * a[ 8]
+ + ((int64_t)a[ 3]) * a[ 7]
+ + ((int64_t)a[ 4]) * a[ 6]) * 2
+ + ((int64_t)a[ 5]) * a[ 5];
+ int64_t t11 = (((int64_t)a[ 2]) * a[ 9]
+ + ((int64_t)a[ 3]) * a[ 8]
+ + ((int64_t)a[ 4]) * a[ 7]
+ + ((int64_t)a[ 5]) * a[ 6]) * 2;
+ int64_t t12 = (((int64_t)a[ 3]) * a[ 9]
+ + ((int64_t)a[ 4]) * a[ 8]
+ + ((int64_t)a[ 5]) * a[ 7]) * 2
+ + ((int64_t)a[ 6]) * a[ 6];
+ int64_t t13 = (((int64_t)a[ 4]) * a[ 9]
+ + ((int64_t)a[ 5]) * a[ 8]
+ + ((int64_t)a[ 6]) * a[ 7]) * 2;
+ int64_t t14 = (((int64_t)a[ 5]) * a[ 9]
+ + ((int64_t)a[ 6]) * a[ 8]) * 2
+ + ((int64_t)a[ 7]) * a[ 7];
+ int64_t t15 = (((int64_t)a[ 6]) * a[ 9]
+ + ((int64_t)a[ 7]) * a[ 8]) * 2;
+ int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2
+ + ((int64_t)a[ 8]) * a[ 8];
+ int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2;
+ int64_t t18 = ((int64_t)a[ 9]) * a[ 9];
+
+ t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
+ t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
+ t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
+ t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
+ t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
+ t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
+ t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
+ t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
+ t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
+ t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
+ t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
+ t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
+ t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
+ t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
+ t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
+ t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
+ t17 += t16 >> 26; r[16] = t16 & 0x3ffffff;
+ t18 += t17 >> 26; r[17] = t17 & 0x3ffffff;
+ r[19] = (sp_digit)(t18 >> 26);
+ r[18] = t18 & 0x3ffffff;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ r[i] = a[i] + b[i];
+ }
+
+ return 0;
+}
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ r[ 0] = a[ 0] + b[ 0];
+ r[ 1] = a[ 1] + b[ 1];
+ r[ 2] = a[ 2] + b[ 2];
+ r[ 3] = a[ 3] + b[ 3];
+ r[ 4] = a[ 4] + b[ 4];
+ r[ 5] = a[ 5] + b[ 5];
+ r[ 6] = a[ 6] + b[ 6];
+ r[ 7] = a[ 7] + b[ 7];
+ r[ 8] = a[ 8] + b[ 8];
+ r[ 9] = a[ 9] + b[ 9];
+
+ return 0;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ r[i] = a[i] - b[i];
+ }
+
+ return 0;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ r[ 0] = a[ 0] - b[ 0];
+ r[ 1] = a[ 1] - b[ 1];
+ r[ 2] = a[ 2] - b[ 2];
+ r[ 3] = a[ 3] - b[ 3];
+ r[ 4] = a[ 4] - b[ 4];
+ r[ 5] = a[ 5] - b[ 5];
+ r[ 6] = a[ 6] - b[ 6];
+ r[ 7] = a[ 7] - b[ 7];
+ r[ 8] = a[ 8] - b[ 8];
+ r[ 9] = a[ 9] - b[ 9];
+
+ return 0;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_10(void* heap, sp_point_256* sp,
+ sp_point_256** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_256_point_free_10(sp_point_256* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 26
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 26
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0x3ffffff;
+ s = 26U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 26U) <= (word32)DIGIT_BIT) {
+ s += 26U;
+ r[j] &= 0x3ffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 26) {
+ r[j] &= 0x3ffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 26 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_256.
+ *
+ * p Point of type sp_point_256 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_256_point_from_ecc_point_10(sp_point_256* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_256_from_mp(p->x, 10, pm->x);
+ sp_256_from_mp(p->y, 10, pm->y);
+ sp_256_from_mp(p->z, 10, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_256_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 26
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 10);
+ r->used = 10;
+ mp_clamp(r);
+#elif DIGIT_BIT < 26
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 10; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 26) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 26 - s;
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 10; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 26 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 26 - s;
+ }
+ else {
+ s += 26;
+ }
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_256 to type ecc_point.
+ *
+ * p Point of type sp_point_256.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_256_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
#define sp_256_mont_reduce_order_10 sp_256_mont_reduce_10
/* Compare a with b in constant time.
@@ -13286,7 +13372,8 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
s = a[10];
n = a[9] >> 22;
@@ -13299,7 +13386,8 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a)
n += s << 4;
r[9] = n;
#else
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
s = a[10]; n = a[9] >> 22;
n += (s & 0x3ffffff) << 4; r[ 0] = n & 0x3ffffff;
@@ -13374,137 +13462,13 @@ static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_256_mul_10(r, a, b);
sp_256_mont_reduce_10(r, m, mp);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
-{
- int i, j, k;
- int64_t c;
-
- c = ((int64_t)a[9]) * a[9];
- r[19] = (sp_digit)(c >> 26);
- c = (c & 0x3ffffff) << 26;
- for (k = 17; k >= 0; k--) {
- for (i = 9; i >= 0; i--) {
- j = k - i;
- if (j >= 10 || i <= j) {
- break;
- }
- if (j < 0) {
- continue;
- }
-
- c += ((int64_t)a[i]) * a[j] * 2;
- }
- if (i == j) {
- c += ((int64_t)a[i]) * a[i];
- }
-
- r[k + 2] += (sp_digit)(c >> 52);
- r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff);
- c = (c & 0x3ffffff) << 26;
- }
- r[0] = (sp_digit)(c >> 26);
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
-{
- int64_t t0 = ((int64_t)a[ 0]) * a[ 0];
- int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2;
- int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2
- + ((int64_t)a[ 1]) * a[ 1];
- int64_t t3 = (((int64_t)a[ 0]) * a[ 3]
- + ((int64_t)a[ 1]) * a[ 2]) * 2;
- int64_t t4 = (((int64_t)a[ 0]) * a[ 4]
- + ((int64_t)a[ 1]) * a[ 3]) * 2
- + ((int64_t)a[ 2]) * a[ 2];
- int64_t t5 = (((int64_t)a[ 0]) * a[ 5]
- + ((int64_t)a[ 1]) * a[ 4]
- + ((int64_t)a[ 2]) * a[ 3]) * 2;
- int64_t t6 = (((int64_t)a[ 0]) * a[ 6]
- + ((int64_t)a[ 1]) * a[ 5]
- + ((int64_t)a[ 2]) * a[ 4]) * 2
- + ((int64_t)a[ 3]) * a[ 3];
- int64_t t7 = (((int64_t)a[ 0]) * a[ 7]
- + ((int64_t)a[ 1]) * a[ 6]
- + ((int64_t)a[ 2]) * a[ 5]
- + ((int64_t)a[ 3]) * a[ 4]) * 2;
- int64_t t8 = (((int64_t)a[ 0]) * a[ 8]
- + ((int64_t)a[ 1]) * a[ 7]
- + ((int64_t)a[ 2]) * a[ 6]
- + ((int64_t)a[ 3]) * a[ 5]) * 2
- + ((int64_t)a[ 4]) * a[ 4];
- int64_t t9 = (((int64_t)a[ 0]) * a[ 9]
- + ((int64_t)a[ 1]) * a[ 8]
- + ((int64_t)a[ 2]) * a[ 7]
- + ((int64_t)a[ 3]) * a[ 6]
- + ((int64_t)a[ 4]) * a[ 5]) * 2;
- int64_t t10 = (((int64_t)a[ 1]) * a[ 9]
- + ((int64_t)a[ 2]) * a[ 8]
- + ((int64_t)a[ 3]) * a[ 7]
- + ((int64_t)a[ 4]) * a[ 6]) * 2
- + ((int64_t)a[ 5]) * a[ 5];
- int64_t t11 = (((int64_t)a[ 2]) * a[ 9]
- + ((int64_t)a[ 3]) * a[ 8]
- + ((int64_t)a[ 4]) * a[ 7]
- + ((int64_t)a[ 5]) * a[ 6]) * 2;
- int64_t t12 = (((int64_t)a[ 3]) * a[ 9]
- + ((int64_t)a[ 4]) * a[ 8]
- + ((int64_t)a[ 5]) * a[ 7]) * 2
- + ((int64_t)a[ 6]) * a[ 6];
- int64_t t13 = (((int64_t)a[ 4]) * a[ 9]
- + ((int64_t)a[ 5]) * a[ 8]
- + ((int64_t)a[ 6]) * a[ 7]) * 2;
- int64_t t14 = (((int64_t)a[ 5]) * a[ 9]
- + ((int64_t)a[ 6]) * a[ 8]) * 2
- + ((int64_t)a[ 7]) * a[ 7];
- int64_t t15 = (((int64_t)a[ 6]) * a[ 9]
- + ((int64_t)a[ 7]) * a[ 8]) * 2;
- int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2
- + ((int64_t)a[ 8]) * a[ 8];
- int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2;
- int64_t t18 = ((int64_t)a[ 9]) * a[ 9];
-
- t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
- t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
- t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
- t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
- t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
- t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
- t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
- t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
- t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
- t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
- t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
- t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
- t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
- t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
- t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
- t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
- t17 += t16 >> 26; r[16] = t16 & 0x3ffffff;
- t18 += t17 >> 26; r[17] = t17 & 0x3ffffff;
- r[19] = (sp_digit)(t18 >> 26);
- r[18] = t18 & 0x3ffffff;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -13512,8 +13476,8 @@ SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_256_sqr_10(r, a);
sp_256_mont_reduce_10(r, m, mp);
@@ -13537,7 +13501,7 @@ static void sp_256_mont_sqr_n_10(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint32_t p256_mod_minus_2[8] = {
@@ -13621,7 +13585,8 @@ static void sp_256_mont_inv_10(sp_digit* r, const sp_digit* a, sp_digit* td)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_10(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_10(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*10;
@@ -13657,49 +13622,6 @@ static void sp_256_map_10(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 10; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- r[ 0] = a[ 0] + b[ 0];
- r[ 1] = a[ 1] + b[ 1];
- r[ 2] = a[ 2] + b[ 2];
- r[ 3] = a[ 3] + b[ 3];
- r[ 4] = a[ 4] + b[ 4];
- r[ 5] = a[ 5] + b[ 5];
- r[ 6] = a[ 6] + b[ 6];
- r[ 7] = a[ 7] + b[ 7];
- r[ 8] = a[ 8] + b[ 8];
- r[ 9] = a[ 9] + b[ 9];
-
- return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -13752,50 +13674,6 @@ static void sp_256_mont_tpl_10(sp_digit* r, const sp_digit* a, const sp_digit* m
sp_256_norm_10(r);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 10; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- r[ 0] = a[ 0] - b[ 0];
- r[ 1] = a[ 1] - b[ 1];
- r[ 2] = a[ 2] - b[ 2];
- r[ 3] = a[ 3] - b[ 3];
- r[ 4] = a[ 4] - b[ 4];
- r[ 5] = a[ 5] - b[ 5];
- r[ 6] = a[ 6] - b[ 6];
- r[ 7] = a[ 7] - b[ 7];
- r[ 8] = a[ 8] - b[ 8];
- r[ 9] = a[ 9] - b[ 9];
-
- return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -13848,13 +13726,13 @@ static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b
* r Result of shift.
* a Number to shift.
*/
-SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, sp_digit* a)
+SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
for (i=0; i<9; i++) {
- r[i] = ((a[i] >> 1) + (a[i + 1] << 25)) & 0x3ffffff;
+ r[i] = (a[i] >> 1) + ((a[i + 1] << 25) & 0x3ffffff);
}
#else
r[0] = (a[0] >> 1) + ((a[1] << 25) & 0x3ffffff);
@@ -14302,8 +14180,8 @@ static int sp_256_proj_point_add_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_10(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -14389,10 +14267,150 @@ static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, con
}
}
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ int64_t* td;
+#else
+ int64_t td[8];
+ int64_t a32d[8];
+#endif
+ int64_t* t;
+ int64_t* a32;
+ int64_t o;
+ int err = MP_OKAY;
+
+ (void)m;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
+ if (td == NULL) {
+ return MEMORY_E;
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ a32 = td + 8;
+#else
+ t = td;
+ a32 = a32d;
+#endif
+
+ a32[0] = a[0];
+ a32[0] |= a[1] << 26U;
+ a32[0] &= 0xffffffffL;
+ a32[1] = (a[1] >> 6);
+ a32[1] |= a[2] << 20U;
+ a32[1] &= 0xffffffffL;
+ a32[2] = (a[2] >> 12);
+ a32[2] |= a[3] << 14U;
+ a32[2] &= 0xffffffffL;
+ a32[3] = (a[3] >> 18);
+ a32[3] |= a[4] << 8U;
+ a32[3] &= 0xffffffffL;
+ a32[4] = (a[4] >> 24);
+ a32[4] |= a[5] << 2U;
+ a32[4] |= a[6] << 28U;
+ a32[4] &= 0xffffffffL;
+ a32[5] = (a[6] >> 4);
+ a32[5] |= a[7] << 22U;
+ a32[5] &= 0xffffffffL;
+ a32[6] = (a[7] >> 10);
+ a32[6] |= a[8] << 16U;
+ a32[6] &= 0xffffffffL;
+ a32[7] = (a[8] >> 16);
+ a32[7] |= a[9] << 10U;
+ a32[7] &= 0xffffffffL;
+
+ /* 1 1 0 -1 -1 -1 -1 0 */
+ t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
+ /* 0 1 1 0 -1 -1 -1 -1 */
+ t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
+ /* 0 0 1 1 0 -1 -1 -1 */
+ t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
+ /* -1 -1 0 2 2 1 0 -1 */
+ t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
+ /* 0 -1 -1 0 2 2 1 0 */
+ t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
+ /* 0 0 -1 -1 0 2 2 1 */
+ t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
+ /* -1 -1 0 0 0 1 3 2 */
+ t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
+ /* 1 0 -1 -1 -1 -1 0 3 */
+ t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
+
+ t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
+ t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
+ t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
+ t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
+ t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
+ t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
+ t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
+ o = t[7] >> 32U; t[7] &= 0xffffffffL;
+ t[0] += o;
+ t[3] -= o;
+ t[6] -= o;
+ t[7] += o;
+ t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
+ t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
+ t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
+ t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
+ t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
+ t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
+ t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
+
+ r[0] = (sp_digit)(t[0]) & 0x3ffffffL;
+ r[1] = (sp_digit)(t[0] >> 26U);
+ r[1] |= (sp_digit)(t[1] << 6U);
+ r[1] &= 0x3ffffffL;
+ r[2] = (sp_digit)(t[1] >> 20U);
+ r[2] |= (sp_digit)(t[2] << 12U);
+ r[2] &= 0x3ffffffL;
+ r[3] = (sp_digit)(t[2] >> 14U);
+ r[3] |= (sp_digit)(t[3] << 18U);
+ r[3] &= 0x3ffffffL;
+ r[4] = (sp_digit)(t[3] >> 8U);
+ r[4] |= (sp_digit)(t[4] << 24U);
+ r[4] &= 0x3ffffffL;
+ r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL;
+ r[6] = (sp_digit)(t[4] >> 28U);
+ r[6] |= (sp_digit)(t[5] << 4U);
+ r[6] &= 0x3ffffffL;
+ r[7] = (sp_digit)(t[5] >> 22U);
+ r[7] |= (sp_digit)(t[6] << 10U);
+ r[7] &= 0x3ffffffL;
+ r[8] = (sp_digit)(t[6] >> 16U);
+ r[8] |= (sp_digit)(t[7] << 16U);
+ r[8] &= 0x3ffffffL;
+ r[9] = (sp_digit)(t[7] >> 10U);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Small implementation using add and double that is cache attack resistant but
+ * allocates memory rather than use large stacks.
+ * 256 adds and doubles.
+ *
* r Resulting point.
* g Point to multiply.
* k Scalar to multiply by.
@@ -14516,8 +14534,8 @@ static int sp_256_ecc_mulmod_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
#endif /* WOLFSSL_SP_NONBLOCK */
-static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp_digit* k,
- int map, int ct, void* heap)
+static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g,
+ const sp_digit* k, int map, int ct, void* heap)
{
#ifdef WOLFSSL_SP_NO_MALLOC
sp_point_256 t[3];
@@ -14528,7 +14546,8 @@ static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp
#endif
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err = MP_OKAY;
/* Implementatio is constant time. */
@@ -14667,7 +14686,8 @@ static void sp_256_cond_copy_10(sp_digit* r, const sp_digit* a, const sp_digit m
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*10;
@@ -14755,8 +14775,8 @@ static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n, sp_digit* t)
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256* p,
- int n, int m, sp_digit* t)
+static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r,
+ const sp_point_256* p, int n, int m, sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*10;
@@ -14767,6 +14787,7 @@ static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256
sp_digit* y = r[(1< .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 42];
+ sp_digit vx[2 * 42];
+ sp_digit vy[2 * 42];
+ sp_digit qx_px[2 * 42];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_42(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 42 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 42 * 2;
+ vy = td + 7 * 42 * 2;
+ qx_px = td + 8 * 42 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_42(p, pm);
+ sp_1024_point_from_ecc_point_42(q, qm);
+
+ err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
+
+ sp_1024_mont_add_42(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 25] >> (i % 25)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_42(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_42(vx, vy, t);
+ sp_1024_proj_sqr_42(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_42(vx, vx, t);
+ sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
+ sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_42(c, 1, NULL);
+ sp_1024_point_free_42(q, 1, NULL);
+ sp_1024_point_free_42(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_42(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 42;
+ sp_digit* rx = t + 4 * 42;
+ sp_digit* ry = t + 6 * 42;
+ sp_digit* h = t + 8 * 42;
+ sp_digit* r = t + 10 * 42;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_42(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_42(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_42(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_42(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_42(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_42(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_42(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_42(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_42(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_42(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_42(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_42(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_42(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_42(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_42(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_42(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_42(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_42(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_42(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_42(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_42(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_42(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 42;
+ sp_digit* pz2 = t + 2 * 42;
+ sp_digit* rx = t + 4 * 42;
+ sp_digit* ry = t + 6 * 42;
+ sp_digit* l = t + 8 * 42;
+ sp_digit* ty = t + 10 * 42;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_42(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_42(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_42(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_42(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_42(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_42(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_42(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_42(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_42(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[84];
+ sp_digit (*pre_vy)[84];
+ sp_digit (*pre_nvy)[84];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 42];
+ sp_digit vx[2 * 42];
+ sp_digit vy[2 * 42];
+ sp_digit pre_vx[16][84];
+ sp_digit pre_vy[16][84];
+ sp_digit pre_nvy[16][84];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_42(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 42 * 2;
+ vy = td + 7 * 42 * 2;
+ pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2);
+ pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2);
+ pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 42 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_42(p, pm);
+ sp_1024_point_from_ecc_point_42(q, qm);
+
+ err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
+ sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
+ sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
+ sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_42(vx, vy, t);
+ sp_1024_proj_sqr_42(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_42(vx, vx, t);
+ sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
+ sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_42(c, 1, NULL);
+ sp_1024_point_free_42(q, 1, NULL);
+ sp_1024_point_free_42(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_42(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 42;
+ sp_digit* t2 = t + 2 * 2 * 42;
+ sp_digit* l = t + 4 * 2 * 42;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_42(l, py, p1024_mod);
+ sp_1024_mont_inv_42(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_42(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_42(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_42(t2, t1, p1024_mod);
+ sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_42(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_42(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_42(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 42);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 42);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_42(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 42;
+ sp_digit* c = t + 2 * 2 * 42;
+ sp_digit* l = t + 4 * 2 * 42;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_42(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_42(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_42(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_42(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_42(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_42(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_42(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_42(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 42);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 42);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_42(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 42;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_42(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_42(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_42(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_42(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 42];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 42 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_42(p, pm);
+
+ err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_42(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_42(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_42(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_42(c, c, t);
+ sp_1024_mont_map_42(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_42(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_42(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_42(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_42(c, c, neg, t);
+ sp_1024_mont_map_42(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_42(c, c, t);
+ sp_1024_mont_map_42(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_42(neg, 1, NULL);
+ sp_1024_point_free_42(c, 1, NULL);
+ sp_1024_point_free_42(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[84];
+ sp_digit (*pre_vy)[84];
+ sp_digit (*pre_nvy)[84];
+#else
+ sp_digit t[6 * 2 * 42];
+ sp_digit vx[2 * 42];
+ sp_digit vy[2 * 42];
+ sp_digit pre_vx[16][84];
+ sp_digit pre_vy[16][84];
+ sp_digit pre_nvy[16][84];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 42 * 2;
+ vy = td + 7 * 42 * 2;
+ pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2);
+ pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2);
+ pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_42(p, pm);
+ sp_1024_point_from_ecc_point_42(q, qm);
+
+ err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
+ sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
+ sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
+ sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 42);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_42(vx, vy, t);
+ sp_1024_proj_sqr_42(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_42(vx, vx, t);
+ sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
+ sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_42(c, 1, NULL);
+ sp_1024_point_free_42(q, 1, NULL);
+ sp_1024_point_free_42(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_42(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
+ a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
+ a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31] |
+ a[32] | a[33] | a[34] | a[35] | a[36] | a[37] | a[38] | a[39] |
+ a[40] | a[41]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = n-1; i >= 0; i--) {
+ r[j] |= (((sp_digit)a[i]) << s);
+ if (s >= 17U) {
+ r[j] &= 0x1ffffff;
+ s = 25U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ r[++j] = (sp_digit)a[i] >> s;
+ s = 8U - s;
+ }
+ else {
+ s += 8U;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_42(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*42];
+ sp_digit t2d[2*42];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int32_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 42;
+ t2 = d + 2 * 42;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_42(t1, point->y);
+ (void)sp_1024_mod_42(t1, t1, p1024_mod);
+ sp_1024_sqr_42(t2, point->x);
+ (void)sp_1024_mod_42(t2, t2, p1024_mod);
+ sp_1024_mul_42(t2, t2, point->x);
+ (void)sp_1024_mod_42(t2, t2, p1024_mod);
+ (void)sp_1024_sub_42(t2, p1024_mod, t2);
+ sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_42(t1, p1024_mod);
+ sp_1024_cond_sub_42(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_42(t1);
+ if (!sp_1024_iszero_42(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_42(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 42, pX);
+ sp_1024_from_mp(pub->y, 42, pY);
+ sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_42(pub, NULL);
+ }
+
+ sp_1024_point_free_42(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[42];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_42(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_42(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 42, pX);
+ sp_1024_from_mp(pub->y, 42, pY);
+ sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 42, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_42(pub->x) != 0) &&
+ (sp_1024_iszero_42(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_42(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_42(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_42(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_42(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_42(p->x) == 0) ||
+ (sp_1024_iszero_42(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_42(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_42(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_42(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_42(p, 0, heap);
+ sp_1024_point_free_42(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* SP_WORD_SIZE == 32 */
#endif /* !WOLFSSL_SP_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c
index 3842b58e0..253bc648b 100644
--- a/wolfcrypt/src/sp_c64.c
+++ b/wolfcrypt/src/sp_c64.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -75,7 +75,8 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 };
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -117,7 +118,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 57
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -151,7 +153,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -190,7 +194,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<35; i++) {
r[i+1] += r[i] >> 57;
@@ -680,7 +687,9 @@ SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[35]) * b[35];
@@ -712,7 +721,9 @@ SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[35]) * a[35];
@@ -792,7 +803,9 @@ SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[17]) * b[17];
@@ -824,7 +837,9 @@ SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[17]) * a[17];
@@ -854,7 +869,7 @@ SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -863,7 +878,8 @@ SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -1181,7 +1197,6 @@ static void sp_2048_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_2048_mul_add_18(a+i, m, mu);
a[i+1] += a[i] >> 57;
a[i] &= 0x1ffffffffffffffL;
-
sp_2048_mont_shift_18(a, a);
sp_2048_cond_sub_18(a, a, m, 0 - (((a[17] >> 55) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -1197,8 +1212,8 @@ static void sp_2048_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_18(r, a, b);
sp_2048_mont_reduce_18(r, m, mp);
@@ -1211,8 +1226,8 @@ static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_18(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_18(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_18(r, a);
sp_2048_mont_reduce_18(r, m, mp);
@@ -1312,50 +1327,13 @@ static void sp_2048_cond_add_18(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 18; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 18; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
#ifdef WOLFSSL_SP_DIV_64
static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 57 bits from d1 and top 6 bits from d0. */
d = (d1 << 6) | (d0 >> 51);
@@ -1440,24 +1418,28 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Large number of bits in last word.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_2048_div_18(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[36], t2d[18 + 1];
+ sp_digit t1d[36];
+ sp_digit t2d[18 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -1485,17 +1467,15 @@ static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m,
dv = d[17];
XMEMCPY(t1, a, sizeof(*t1) * 2U * 18U);
for (i=17; i>=0; i--) {
- sp_digit hi;
t1[18 + i] += t1[18 + i - 1] >> 57;
t1[18 + i - 1] &= 0x1ffffffffffffffL;
- hi = t1[18 + i] - (t1[18 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[18 + i];
d1 <<= 57;
d1 += t1[18 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_2048_div_word_18(hi, t1[18 + i - 1], dv);
+ r1 = sp_2048_div_word_18(t1[18 + i], t1[18 + i - 1], dv);
#endif
sp_2048_mul_d_18(t2, d, r1);
@@ -1516,7 +1496,7 @@ static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_18(t2, d, r1);
(void)sp_2048_sub_18(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 18U);
+ XMEMCPY(r, t1, sizeof(*r) * 36U);
for (i=0; i<17; i++) {
r[i+1] += r[i] >> 57;
r[i] &= 0x1ffffffffffffffL;
@@ -1569,7 +1549,8 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -1660,7 +1641,8 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -1746,12 +1728,13 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 36) + 36];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -1843,7 +1826,7 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 36);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -1878,7 +1861,7 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 2048 bits, just need to subtract.
@@ -2086,7 +2069,8 @@ static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
s = a[36];
n = a[35] >> 53;
@@ -2099,7 +2083,8 @@ static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a)
n += s << 4;
r[35] = n;
#else
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
int i;
s = a[36]; n = a[35] >> 53;
@@ -2145,7 +2130,7 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_2048_norm_36(a + 36);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<35; i++) {
mu = (a[i] * mp) & 0x1ffffffffffffffL;
@@ -2179,7 +2164,6 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 57;
a[i] &= 0x1ffffffffffffffL;
#endif
-
sp_2048_mont_shift_36(a, a);
sp_2048_cond_sub_36(a, a, m, 0 - (((a[35] >> 53) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -2195,8 +2179,8 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_36(r, a, b);
sp_2048_mont_reduce_36(r, m, mp);
@@ -2209,8 +2193,8 @@ static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_36(r, a);
sp_2048_mont_reduce_36(r, m, mp);
@@ -2253,50 +2237,13 @@ static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 36; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 36; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
#ifdef WOLFSSL_SP_DIV_64
static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 57 bits from d1 and top 6 bits from d0. */
d = (d1 << 6) | (d0 >> 51);
@@ -2381,24 +2328,28 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Large number of bits in last word.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_2048_div_36(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[72], t2d[36 + 1];
+ sp_digit t1d[72];
+ sp_digit t2d[36 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -2426,17 +2377,15 @@ static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m,
dv = d[35];
XMEMCPY(t1, a, sizeof(*t1) * 2U * 36U);
for (i=35; i>=0; i--) {
- sp_digit hi;
t1[36 + i] += t1[36 + i - 1] >> 57;
t1[36 + i - 1] &= 0x1ffffffffffffffL;
- hi = t1[36 + i] - (t1[36 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[36 + i];
d1 <<= 57;
d1 += t1[36 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_2048_div_word_36(hi, t1[36 + i - 1], dv);
+ r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv);
#endif
sp_2048_mul_d_36(t2, d, r1);
@@ -2457,7 +2406,7 @@ static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_2048_mul_d_36(t2, d, r1);
(void)sp_2048_sub_36(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 36U);
+ XMEMCPY(r, t1, sizeof(*r) * 72U);
for (i=0; i<35; i++) {
r[i+1] += r[i] >> 57;
r[i] &= 0x1ffffffffffffffL;
@@ -2512,7 +2461,8 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2603,7 +2553,8 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -2689,12 +2640,13 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 72) + 72];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2786,7 +2738,7 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 72);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -2820,7 +2772,7 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -2836,15 +2788,15 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -2937,13 +2889,15 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[72], md[36], rd[72];
+ sp_digit ad[72];
+ sp_digit md[36];
+ sp_digit rd[72];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -3061,7 +3015,7 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -3079,9 +3033,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3144,7 +3098,9 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[72], d[36], m[36];
+ sp_digit a[72];
+ sp_digit d[36];
+ sp_digit m[36];
sp_digit* r = a;
int err = MP_OKAY;
@@ -3187,19 +3143,19 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 36);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -3274,8 +3230,13 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[36 * 2];
- sp_digit p[18], q[18], dp[18], dq[18], qi[18];
- sp_digit tmpa[36], tmpb[36];
+ sp_digit p[18];
+ sp_digit q[18];
+ sp_digit dp[18];
+ sp_digit dq[18];
+ sp_digit qi[18];
+ sp_digit tmpa[36];
+ sp_digit tmpb[36];
sp_digit* r = a;
int err = MP_OKAY;
@@ -3337,8 +3298,8 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -3361,17 +3322,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 36;
mp_clamp(r);
#elif DIGIT_BIT < 57
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 36; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 57) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -3384,14 +3347,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 36; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 57 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -3418,7 +3383,8 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -3474,7 +3440,9 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[72], ed[36], md[36];
+ sp_digit bd[72];
+ sp_digit ed[36];
+ sp_digit md[36];
#else
sp_digit* d = NULL;
#endif
@@ -3546,7 +3514,8 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_2048
-SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -3556,7 +3525,8 @@ SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[35];
r[36] = s >> (57U - n);
@@ -3652,9 +3622,11 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3699,7 +3671,7 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const
n <<= 5;
c -= 5;
sp_2048_lshift_36(r, norm, (byte)y);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -3754,8 +3726,8 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -3822,7 +3794,9 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[72], ed[36], md[36];
+ sp_digit bd[72];
+ sp_digit ed[36];
+ sp_digit md[36];
#else
sp_digit* d = NULL;
#endif
@@ -3887,6 +3861,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -3915,7 +3890,8 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -3972,7 +3948,9 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[36], ed[18], md[18];
+ sp_digit bd[36];
+ sp_digit ed[18];
+ sp_digit md[18];
#else
sp_digit* d = NULL;
#endif
@@ -4042,7 +4020,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#endif
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -4056,7 +4034,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -4098,7 +4077,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 57
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -4132,7 +4112,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -4171,7 +4153,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<53; i++) {
r[i+1] += r[i] >> 57;
@@ -4773,7 +4758,9 @@ SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[53]) * b[53];
@@ -4805,7 +4792,9 @@ SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[53]) * a[53];
@@ -4943,7 +4932,9 @@ SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[26]) * b[26];
@@ -4978,7 +4969,8 @@ SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j;
+ int i;
+ int j;
int128_t t[54];
XMEMSET(t, 0, sizeof(t));
@@ -5003,7 +4995,9 @@ SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[26]) * a[26];
@@ -5040,7 +5034,8 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
*/
SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
{
- int i, j;
+ int i;
+ int j;
int128_t t[54];
XMEMSET(t, 0, sizeof(t));
@@ -5058,7 +5053,7 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -5067,7 +5062,8 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -5342,7 +5338,8 @@ static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
s = a[27];
n = a[26] >> 54;
@@ -5355,7 +5352,8 @@ static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a)
n += s << 3;
r[26] = n;
#else
- sp_digit n, s;
+ sp_digit n;
+ sp_digit s;
int i;
s = a[27]; n = a[26] >> 54;
@@ -5408,7 +5406,6 @@ static void sp_3072_mont_reduce_27(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_3072_mul_add_27(a+i, m, mu);
a[i+1] += a[i] >> 57;
a[i] &= 0x1ffffffffffffffL;
-
sp_3072_mont_shift_27(a, a);
sp_3072_cond_sub_27(a, a, m, 0 - (((a[26] >> 54) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -5424,8 +5421,8 @@ static void sp_3072_mont_reduce_27(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_27(r, a, b);
sp_3072_mont_reduce_27(r, m, mp);
@@ -5438,8 +5435,8 @@ static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_27(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_27(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_27(r, a);
sp_3072_mont_reduce_27(r, m, mp);
@@ -5547,7 +5544,9 @@ static void sp_3072_cond_add_27(sp_digit* r, const sp_digit* a,
static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 57 bits from d1 and top 6 bits from d0. */
d = (d1 << 6) | (d0 >> 51);
@@ -5632,24 +5631,28 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Large number of bits in last word.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_3072_div_27(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[54], t2d[27 + 1];
+ sp_digit t1d[54];
+ sp_digit t2d[27 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -5677,17 +5680,15 @@ static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m,
dv = d[26];
XMEMCPY(t1, a, sizeof(*t1) * 2U * 27U);
for (i=26; i>=0; i--) {
- sp_digit hi;
t1[27 + i] += t1[27 + i - 1] >> 57;
t1[27 + i - 1] &= 0x1ffffffffffffffL;
- hi = t1[27 + i] - (t1[27 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[27 + i];
d1 <<= 57;
d1 += t1[27 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_3072_div_word_27(hi, t1[27 + i - 1], dv);
+ r1 = sp_3072_div_word_27(t1[27 + i], t1[27 + i - 1], dv);
#endif
sp_3072_mul_d_27(t2, d, r1);
@@ -5708,7 +5709,7 @@ static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_3072_mul_d_27(t2, d, r1);
(void)sp_3072_sub_27(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 27U);
+ XMEMCPY(r, t1, sizeof(*r) * 54U);
for (i=0; i<26; i++) {
r[i+1] += r[i] >> 57;
r[i] &= 0x1ffffffffffffffL;
@@ -5761,7 +5762,8 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5852,7 +5854,8 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -5938,12 +5941,13 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 54) + 54];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6035,7 +6039,7 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 54);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -6070,7 +6074,7 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 3072 bits, just need to subtract.
@@ -6342,7 +6346,7 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_3072_norm_54(a + 54);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<53; i++) {
mu = (a[i] * mp) & 0x1ffffffffffffffL;
@@ -6376,7 +6380,6 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 57;
a[i] &= 0x1ffffffffffffffL;
#endif
-
sp_3072_mont_shift_54(a, a);
sp_3072_cond_sub_54(a, a, m, 0 - (((a[53] >> 51) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -6392,8 +6395,8 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_54(r, a, b);
sp_3072_mont_reduce_54(r, m, mp);
@@ -6406,8 +6409,8 @@ static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_54(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_54(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_54(r, a);
sp_3072_mont_reduce_54(r, m, mp);
@@ -6456,7 +6459,9 @@ static void sp_3072_cond_add_54(sp_digit* r, const sp_digit* a,
static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 57 bits from d1 and top 6 bits from d0. */
d = (d1 << 6) | (d0 >> 51);
@@ -6541,24 +6546,28 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Large number of bits in last word.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_3072_div_54(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[108], t2d[54 + 1];
+ sp_digit t1d[108];
+ sp_digit t2d[54 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -6586,17 +6595,15 @@ static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m,
dv = d[53];
XMEMCPY(t1, a, sizeof(*t1) * 2U * 54U);
for (i=53; i>=0; i--) {
- sp_digit hi;
t1[54 + i] += t1[54 + i - 1] >> 57;
t1[54 + i - 1] &= 0x1ffffffffffffffL;
- hi = t1[54 + i] - (t1[54 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[54 + i];
d1 <<= 57;
d1 += t1[54 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_3072_div_word_54(hi, t1[54 + i - 1], dv);
+ r1 = sp_3072_div_word_54(t1[54 + i], t1[54 + i - 1], dv);
#endif
sp_3072_mul_d_54(t2, d, r1);
@@ -6617,7 +6624,7 @@ static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_3072_mul_d_54(t2, d, r1);
(void)sp_3072_sub_54(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 54U);
+ XMEMCPY(r, t1, sizeof(*r) * 108U);
for (i=0; i<53; i++) {
r[i+1] += r[i] >> 57;
r[i] &= 0x1ffffffffffffffL;
@@ -6672,7 +6679,8 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6763,7 +6771,8 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -6849,12 +6858,13 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 108) + 108];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6946,7 +6956,7 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 108);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -6980,7 +6990,7 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -6996,15 +7006,15 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -7097,13 +7107,15 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[108], md[54], rd[108];
+ sp_digit ad[108];
+ sp_digit md[54];
+ sp_digit rd[108];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -7221,7 +7233,7 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -7239,9 +7251,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7304,7 +7316,9 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[108], d[54], m[54];
+ sp_digit a[108];
+ sp_digit d[54];
+ sp_digit m[54];
sp_digit* r = a;
int err = MP_OKAY;
@@ -7347,19 +7361,19 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 54);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -7434,8 +7448,13 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[54 * 2];
- sp_digit p[27], q[27], dp[27], dq[27], qi[27];
- sp_digit tmpa[54], tmpb[54];
+ sp_digit p[27];
+ sp_digit q[27];
+ sp_digit dp[27];
+ sp_digit dq[27];
+ sp_digit qi[27];
+ sp_digit tmpa[54];
+ sp_digit tmpb[54];
sp_digit* r = a;
int err = MP_OKAY;
@@ -7497,8 +7516,8 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -7521,17 +7540,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 54;
mp_clamp(r);
#elif DIGIT_BIT < 57
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 54; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 57) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -7544,14 +7565,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 54; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 57 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -7578,7 +7601,8 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -7634,7 +7658,9 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[108], ed[54], md[54];
+ sp_digit bd[108];
+ sp_digit ed[54];
+ sp_digit md[54];
#else
sp_digit* d = NULL;
#endif
@@ -7706,7 +7732,8 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_3072
-SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -7716,7 +7743,8 @@ SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[53];
r[54] = s >> (57U - n);
@@ -7848,9 +7876,11 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -7895,7 +7925,7 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const
n <<= 5;
c -= 5;
sp_3072_lshift_54(r, norm, (byte)y);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (7 - c);
c += 57;
@@ -7950,8 +7980,8 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -8018,7 +8048,9 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[108], ed[54], md[54];
+ sp_digit bd[108];
+ sp_digit ed[54];
+ sp_digit md[54];
#else
sp_digit* d = NULL;
#endif
@@ -8083,6 +8115,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -8111,7 +8144,8 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -8168,7 +8202,9 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[54], ed[27], md[27];
+ sp_digit bd[54];
+ sp_digit ed[27];
+ sp_digit md[27];
#else
sp_digit* d = NULL;
#endif
@@ -8238,7 +8274,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#endif
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -8252,7 +8288,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8294,7 +8331,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 53
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -8328,7 +8366,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -8367,7 +8407,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
for (i=0; i<77; i++) {
r[i+1] += r[i] >> 53;
@@ -9095,7 +9138,9 @@ SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[77]) * b[77];
@@ -9127,7 +9172,9 @@ SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_4096_sqr_78(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[77]) * a[77];
@@ -9241,7 +9288,9 @@ SP_NOINLINE static int sp_4096_sub_39(sp_digit* r, const sp_digit* a,
SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[38]) * b[38];
@@ -9273,7 +9322,9 @@ SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a,
*/
SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[38]) * a[38];
@@ -9303,8 +9354,8 @@ SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */
-#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
+#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
+#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -9313,7 +9364,8 @@ SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -9673,7 +9725,6 @@ static void sp_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_4096_mul_add_39(a+i, m, mu);
a[i+1] += a[i] >> 53;
a[i] &= 0x1fffffffffffffL;
-
sp_4096_mont_shift_39(a, a);
sp_4096_cond_sub_39(a, a, m, 0 - (((a[38] >> 34) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -9689,8 +9740,8 @@ static void sp_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_39(r, a, b);
sp_4096_mont_reduce_39(r, m, mp);
@@ -9703,8 +9754,8 @@ static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_39(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_39(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_39(r, a);
sp_4096_mont_reduce_39(r, m, mp);
@@ -9812,26 +9863,8 @@ static void sp_4096_cond_add_39(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_add_39(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 39; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -9841,21 +9874,21 @@ SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<32; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (53 - n)) & 0x1fffffffffffffL);
}
- r[32] = ((a[32] >> n) | (a[33] << (53 - n))) & 0x1fffffffffffffL;
- r[33] = ((a[33] >> n) | (a[34] << (53 - n))) & 0x1fffffffffffffL;
- r[34] = ((a[34] >> n) | (a[35] << (53 - n))) & 0x1fffffffffffffL;
- r[35] = ((a[35] >> n) | (a[36] << (53 - n))) & 0x1fffffffffffffL;
- r[36] = ((a[36] >> n) | (a[37] << (53 - n))) & 0x1fffffffffffffL;
- r[37] = ((a[37] >> n) | (a[38] << (53 - n))) & 0x1fffffffffffffL;
+ r[32] = (a[32] >> n) | ((a[33] << (53 - n)) & 0x1fffffffffffffL);
+ r[33] = (a[33] >> n) | ((a[34] << (53 - n)) & 0x1fffffffffffffL);
+ r[34] = (a[34] >> n) | ((a[35] << (53 - n)) & 0x1fffffffffffffL);
+ r[35] = (a[35] >> n) | ((a[36] << (53 - n)) & 0x1fffffffffffffL);
+ r[36] = (a[36] >> n) | ((a[37] << (53 - n)) & 0x1fffffffffffffL);
+ r[37] = (a[37] >> n) | ((a[38] << (53 - n)) & 0x1fffffffffffffL);
#endif
r[38] = a[38] >> n;
}
@@ -9864,7 +9897,9 @@ SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 53 bits from d1 and top 10 bits from d0. */
d = (d1 << 10) | (d0 >> 43);
@@ -9917,24 +9952,29 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_4096_div_39(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[78 + 1], t2d[39 + 1], sdd[39 + 1];
+ sp_digit t1d[78 + 1];
+ sp_digit t2d[39 + 1];
+ sp_digit sdd[39 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -9967,18 +10007,16 @@ static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_39(sd, d, 1L << 19);
sp_4096_mul_d_78(t1, a, 1L << 19);
dv = sd[38];
+ t1[39 + 39] += t1[39 + 39 - 1] >> 53;
+ t1[39 + 39 - 1] &= 0x1fffffffffffffL;
for (i=39; i>=0; i--) {
- sp_digit hi;
- t1[39 + i] += t1[39 + i - 1] >> 53;
- t1[39 + i - 1] &= 0x1fffffffffffffL;
- hi = t1[39 + i] - (t1[39 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[39 + i];
d1 <<= 53;
d1 += t1[39 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_4096_div_word_39(hi, t1[39 + i - 1], dv);
+ r1 = sp_4096_div_word_39(t1[39 + i], t1[39 + i - 1], dv);
#endif
sp_4096_mul_d_39(t2, sd, r1);
@@ -9999,7 +10037,7 @@ static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_39(t2, sd, r1);
sp_4096_sub_39(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 39U);
+ XMEMCPY(r, t1, sizeof(*r) * 78U);
for (i=0; i<38; i++) {
r[i+1] += r[i] >> 53;
r[i] &= 0x1fffffffffffffL;
@@ -10055,7 +10093,8 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10146,7 +10185,8 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -10232,12 +10272,13 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 78) + 78];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10329,7 +10370,7 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 78);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (11 - c);
c += 53;
@@ -10364,8 +10405,8 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e,
#endif
}
-#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */
-#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
+#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
+#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 4096 bits, just need to subtract.
@@ -10637,7 +10678,7 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp)
sp_4096_norm_78(a + 78);
-#ifdef WOLFSSL_HAVE_SP_DH
+#ifdef WOLFSSL_SP_DH
if (mp != 1) {
for (i=0; i<77; i++) {
mu = (a[i] * mp) & 0x1fffffffffffffL;
@@ -10671,7 +10712,6 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp)
a[i+1] += a[i] >> 53;
a[i] &= 0x1fffffffffffffL;
#endif
-
sp_4096_mont_shift_78(a, a);
sp_4096_cond_sub_78(a, a, m, 0 - (((a[77] >> 15) > 0) ?
(sp_digit)1 : (sp_digit)0));
@@ -10687,8 +10727,8 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_78(r, a, b);
sp_4096_mont_reduce_78(r, m, mp);
@@ -10701,8 +10741,8 @@ static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_78(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_78(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_78(r, a);
sp_4096_mont_reduce_78(r, m, mp);
@@ -10800,46 +10840,8 @@ static void sp_4096_cond_add_78(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 78; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_4096_add_78(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 78; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#endif
-SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, const sp_digit* a,
+ byte n)
{
int i;
@@ -10849,20 +10851,20 @@ SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n)
}
#else
for (i=0; i<72; i += 8) {
- r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL;
- r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL;
- r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL;
- r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL;
- r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL;
- r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL;
- r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL;
- r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL;
+ r[i+0] = (a[i+0] >> n) | ((a[i+1] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+1] = (a[i+1] >> n) | ((a[i+2] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+2] = (a[i+2] >> n) | ((a[i+3] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+3] = (a[i+3] >> n) | ((a[i+4] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+4] = (a[i+4] >> n) | ((a[i+5] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+5] = (a[i+5] >> n) | ((a[i+6] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+6] = (a[i+6] >> n) | ((a[i+7] << (53 - n)) & 0x1fffffffffffffL);
+ r[i+7] = (a[i+7] >> n) | ((a[i+8] << (53 - n)) & 0x1fffffffffffffL);
}
- r[72] = ((a[72] >> n) | (a[73] << (53 - n))) & 0x1fffffffffffffL;
- r[73] = ((a[73] >> n) | (a[74] << (53 - n))) & 0x1fffffffffffffL;
- r[74] = ((a[74] >> n) | (a[75] << (53 - n))) & 0x1fffffffffffffL;
- r[75] = ((a[75] >> n) | (a[76] << (53 - n))) & 0x1fffffffffffffL;
- r[76] = ((a[76] >> n) | (a[77] << (53 - n))) & 0x1fffffffffffffL;
+ r[72] = (a[72] >> n) | ((a[73] << (53 - n)) & 0x1fffffffffffffL);
+ r[73] = (a[73] >> n) | ((a[74] << (53 - n)) & 0x1fffffffffffffL);
+ r[74] = (a[74] >> n) | ((a[75] << (53 - n)) & 0x1fffffffffffffL);
+ r[75] = (a[75] >> n) | ((a[76] << (53 - n)) & 0x1fffffffffffffL);
+ r[76] = (a[76] >> n) | ((a[77] << (53 - n)) & 0x1fffffffffffffL);
#endif
r[77] = a[77] >> n;
}
@@ -10871,7 +10873,9 @@ SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n)
static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0,
sp_digit dv)
{
- sp_digit d, r, t;
+ sp_digit d;
+ sp_digit r;
+ sp_digit t;
/* All 53 bits from d1 and top 10 bits from d0. */
d = (d1 << 10) | (d0 >> 43);
@@ -10924,24 +10928,29 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0,
/* Divide d in a and put remainder into r (m*d + r = a)
* m is not calculated as it is not needed at this time.
*
+ * Full implementation.
+ *
* a Number to be divided.
* d Number to divide with.
* m Multiplier result.
* r Remainder from the division.
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
*/
-static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
+static int sp_4096_div_78(const sp_digit* a, const sp_digit* d,
+ const sp_digit* m, sp_digit* r)
{
int i;
#ifndef WOLFSSL_SP_DIV_64
int128_t d1;
#endif
- sp_digit dv, r1;
+ sp_digit dv;
+ sp_digit r1;
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* td;
#else
- sp_digit t1d[156 + 1], t2d[78 + 1], sdd[78 + 1];
+ sp_digit t1d[156 + 1];
+ sp_digit t2d[78 + 1];
+ sp_digit sdd[78 + 1];
#endif
sp_digit* t1;
sp_digit* t2;
@@ -10974,18 +10983,16 @@ static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_78(sd, d, 1L << 38);
sp_4096_mul_d_156(t1, a, 1L << 38);
dv = sd[77];
+ t1[78 + 78] += t1[78 + 78 - 1] >> 53;
+ t1[78 + 78 - 1] &= 0x1fffffffffffffL;
for (i=78; i>=0; i--) {
- sp_digit hi;
- t1[78 + i] += t1[78 + i - 1] >> 53;
- t1[78 + i - 1] &= 0x1fffffffffffffL;
- hi = t1[78 + i] - (t1[78 + i] == dv);
#ifndef WOLFSSL_SP_DIV_64
- d1 = hi;
+ d1 = t1[78 + i];
d1 <<= 53;
d1 += t1[78 + i - 1];
r1 = (sp_digit)(d1 / dv);
#else
- r1 = sp_4096_div_word_78(hi, t1[78 + i - 1], dv);
+ r1 = sp_4096_div_word_78(t1[78 + i], t1[78 + i - 1], dv);
#endif
sp_4096_mul_d_78(t2, sd, r1);
@@ -11006,7 +11013,7 @@ static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_4096_mul_d_78(t2, sd, r1);
sp_4096_sub_78(t1, t1, t2);
- XMEMCPY(r, t1, sizeof(*r) * 2U * 78U);
+ XMEMCPY(r, t1, sizeof(*r) * 156U);
for (i=0; i<77; i++) {
r[i+1] += r[i] >> 53;
r[i] &= 0x1fffffffffffffL;
@@ -11064,7 +11071,8 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11155,7 +11163,8 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#ifdef WOLFSSL_SMALL_STACK
@@ -11241,12 +11250,13 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(32 * 156) + 156];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11338,7 +11348,7 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
n <<= 5;
c -= 5;
XMEMCPY(rt, t[y], sizeof(sp_digit) * 156);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (11 - c);
c += 53;
@@ -11372,7 +11382,7 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
return err;
#endif
}
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
/* WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_RSA
@@ -11388,15 +11398,15 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
sp_digit* d = NULL;
sp_digit* a = NULL;
sp_digit* m = NULL;
sp_digit* r = NULL;
- sp_digit* norm;
+ sp_digit* norm = NULL;
sp_digit e[1] = {0};
sp_digit mp;
int i;
@@ -11489,13 +11499,15 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
return err;
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[156], md[78], rd[156];
+ sp_digit ad[156];
+ sp_digit md[78];
+ sp_digit rd[156];
#else
sp_digit* d = NULL;
#endif
- sp_digit* a;
- sp_digit* m;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* m = NULL;
+ sp_digit* r = NULL;
sp_digit e[1] = {0};
int err = MP_OKAY;
@@ -11613,7 +11625,7 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
-#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */
+#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
/* RSA private key operation.
*
* in Array of bytes representing the number to exponentiate, base.
@@ -11631,9 +11643,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -11696,7 +11708,9 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
- sp_digit a[156], d[78], m[78];
+ sp_digit a[156];
+ sp_digit d[78];
+ sp_digit m[78];
sp_digit* r = a;
int err = MP_OKAY;
@@ -11739,19 +11753,19 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(d, 0, sizeof(sp_digit) * 78);
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
#else
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* t = NULL;
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
+ sp_digit* a = NULL;
+ sp_digit* p = NULL;
+ sp_digit* q = NULL;
+ sp_digit* dp = NULL;
+ sp_digit* dq = NULL;
+ sp_digit* qi = NULL;
+ sp_digit* tmpa = NULL;
+ sp_digit* tmpb = NULL;
+ sp_digit* r = NULL;
int err = MP_OKAY;
(void)dm;
@@ -11826,8 +11840,13 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
return err;
#else
sp_digit a[78 * 2];
- sp_digit p[39], q[39], dp[39], dq[39], qi[39];
- sp_digit tmpa[78], tmpb[78];
+ sp_digit p[39];
+ sp_digit q[39];
+ sp_digit dp[39];
+ sp_digit dq[39];
+ sp_digit qi[39];
+ sp_digit tmpa[78];
+ sp_digit tmpb[78];
sp_digit* r = a;
int err = MP_OKAY;
@@ -11889,8 +11908,8 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(qi, 0, sizeof(qi));
return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* WOLFSSL_SP_SMALL | defined(WOLFSSL_SMALL_STACK) */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
}
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
@@ -11913,17 +11932,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 78;
mp_clamp(r);
#elif DIGIT_BIT < 53
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 78; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 53) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -11936,14 +11957,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 78; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 53 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -11970,7 +11993,8 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -12026,7 +12050,9 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[156], ed[78], md[78];
+ sp_digit bd[156];
+ sp_digit ed[78];
+ sp_digit md[78];
#else
sp_digit* d = NULL;
#endif
@@ -12098,7 +12124,8 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
#ifdef WOLFSSL_HAVE_SP_DH
#ifdef HAVE_FFDHE_4096
-SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n)
+SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, const sp_digit* a,
+ byte n)
{
#ifdef WOLFSSL_SP_SMALL
int i;
@@ -12108,7 +12135,8 @@ SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n)
r[i] = ((a[i] << n) | (a[i-1] >> (53 - n))) & 0x1fffffffffffffL;
}
#else
- sp_int_digit s, t;
+ sp_int_digit s;
+ sp_int_digit t;
s = (sp_int_digit)a[77];
r[78] = s >> (53U - n);
@@ -12288,9 +12316,11 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12335,7 +12365,7 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const
n <<= 5;
c -= 5;
sp_4096_lshift_78(r, norm, (byte)y);
- for (; i>=0 || c>=5; ) {
+ while ((i >= 0) || (c >= 5)) {
if (c < 5) {
n |= e[i--] << (11 - c);
c += 53;
@@ -12390,8 +12420,8 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
#ifdef WOLFSSL_SP_SMALL
int err = MP_OKAY;
@@ -12458,7 +12488,9 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
return err;
#else
#ifndef WOLFSSL_SMALL_STACK
- sp_digit bd[156], ed[78], md[78];
+ sp_digit bd[156];
+ sp_digit ed[78];
+ sp_digit md[78];
#else
sp_digit* d = NULL;
#endif
@@ -12523,6 +12555,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512U && out[i] == 0U; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -12542,19 +12575,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 5];
+ /* Y ordinate of point. */
sp_digit y[2 * 5];
+ /* Z ordinate of point. */
sp_digit z[2 * 5];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -12624,353 +12661,6 @@ static const sp_digit p256_b[5] = {
};
#endif
-static int sp_256_point_new_ex_5(void* heap, sp_point_256* sp, sp_point_256** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), &(sp), &(p))
-#endif
-
-
-static void sp_256_point_free_5(sp_point_256* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mod_mul_norm_5(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- int64_t* td;
-#else
- int64_t td[8];
- int64_t a32d[8];
-#endif
- int64_t* t;
- int64_t* a32;
- int64_t o;
- int err = MP_OKAY;
-
- (void)m;
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
- if (td == NULL) {
- return MEMORY_E;
- }
-#endif
-
- if (err == MP_OKAY) {
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- t = td;
- a32 = td + 8;
-#else
- t = td;
- a32 = a32d;
-#endif
-
- a32[0] = (sp_digit)(a[0]) & 0xffffffffL;
- a32[1] = (sp_digit)(a[0] >> 32U);
- a32[1] |= (sp_digit)(a[1] << 20U);
- a32[1] &= 0xffffffffL;
- a32[2] = (sp_digit)(a[1] >> 12U) & 0xffffffffL;
- a32[3] = (sp_digit)(a[1] >> 44U);
- a32[3] |= (sp_digit)(a[2] << 8U);
- a32[3] &= 0xffffffffL;
- a32[4] = (sp_digit)(a[2] >> 24U);
- a32[4] |= (sp_digit)(a[3] << 28U);
- a32[4] &= 0xffffffffL;
- a32[5] = (sp_digit)(a[3] >> 4U) & 0xffffffffL;
- a32[6] = (sp_digit)(a[3] >> 36U);
- a32[6] |= (sp_digit)(a[4] << 16U);
- a32[6] &= 0xffffffffL;
- a32[7] = (sp_digit)(a[4] >> 16U) & 0xffffffffL;
-
- /* 1 1 0 -1 -1 -1 -1 0 */
- t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
- /* 0 1 1 0 -1 -1 -1 -1 */
- t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
- /* 0 0 1 1 0 -1 -1 -1 */
- t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
- /* -1 -1 0 2 2 1 0 -1 */
- t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
- /* 0 -1 -1 0 2 2 1 0 */
- t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
- /* 0 0 -1 -1 0 2 2 1 */
- t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
- /* -1 -1 0 0 0 1 3 2 */
- t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
- /* 1 0 -1 -1 -1 -1 0 3 */
- t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
- t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
- t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
- t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
- t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
- t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
- t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
- t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
- o = t[7] >> 32U; t[7] &= 0xffffffffL;
- t[0] += o;
- t[3] -= o;
- t[6] -= o;
- t[7] += o;
- t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
- t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
- t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
- t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
- t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
- t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
- t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
-
- r[0] = t[0];
- r[0] |= t[1] << 32U;
- r[0] &= 0xfffffffffffffLL;
- r[1] = (sp_digit)(t[1] >> 20);
- r[1] |= t[2] << 12U;
- r[1] |= t[3] << 44U;
- r[1] &= 0xfffffffffffffLL;
- r[2] = (sp_digit)(t[3] >> 8);
- r[2] |= t[4] << 24U;
- r[2] &= 0xfffffffffffffLL;
- r[3] = (sp_digit)(t[4] >> 28);
- r[3] |= t[5] << 4U;
- r[3] |= t[6] << 36U;
- r[3] &= 0xfffffffffffffLL;
- r[4] = (sp_digit)(t[6] >> 16);
- r[4] |= t[7] << 16U;
- }
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_ECC);
- }
-#endif
-
- return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 52
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 52
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xfffffffffffffL;
- s = 52U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 52U) <= (word32)DIGIT_BIT) {
- s += 52U;
- r[j] &= 0xfffffffffffffL;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 52) {
- r[j] &= 0xfffffffffffffL;
- if (j + 1 >= size) {
- break;
- }
- s = 52 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_256.
- *
- * p Point of type sp_point_256 (result).
- * pm Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_5(sp_point_256* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_256_from_mp(p->x, 5, pm->x);
- sp_256_from_mp(p->y, 5, pm->y);
- sp_256_from_mp(p->z, 5, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_256_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 52
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 5);
- r->used = 5;
- mp_clamp(r);
-#elif DIGIT_BIT < 52
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 5; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 52) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 52 - s;
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 5; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 52 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 52 - s;
- }
- else {
- s += 52;
- }
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_256 to type ecc_point.
- *
- * p Point of type sp_point_256.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm)
-{
- int err;
-
- err = sp_256_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
#ifdef WOLFSSL_SP_SMALL
/* Multiply a and b into r. (r = a * b)
*
@@ -12981,7 +12671,9 @@ static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm)
SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a,
const sp_digit* b)
{
- int i, j, k;
+ int i;
+ int j;
+ int k;
int128_t c;
c = ((int128_t)a[4]) * b[4];
@@ -13055,6 +12747,409 @@ SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a,
}
#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
+{
+ int i;
+ int j;
+ int k;
+ int128_t c;
+
+ c = ((int128_t)a[4]) * a[4];
+ r[9] = (sp_digit)(c >> 52);
+ c = (c & 0xfffffffffffffL) << 52;
+ for (k = 7; k >= 0; k--) {
+ for (i = 4; i >= 0; i--) {
+ j = k - i;
+ if (j >= 5 || i <= j) {
+ break;
+ }
+ if (j < 0) {
+ continue;
+ }
+
+ c += ((int128_t)a[i]) * a[j] * 2;
+ }
+ if (i == j) {
+ c += ((int128_t)a[i]) * a[i];
+ }
+
+ r[k + 2] += (sp_digit)(c >> 104);
+ r[k + 1] = (sp_digit)((c >> 52) & 0xfffffffffffffL);
+ c = (c & 0xfffffffffffffL) << 52;
+ }
+ r[0] = (sp_digit)(c >> 52);
+}
+
+#else
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
+{
+ int128_t t0 = ((int128_t)a[ 0]) * a[ 0];
+ int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2;
+ int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2
+ + ((int128_t)a[ 1]) * a[ 1];
+ int128_t t3 = (((int128_t)a[ 0]) * a[ 3]
+ + ((int128_t)a[ 1]) * a[ 2]) * 2;
+ int128_t t4 = (((int128_t)a[ 0]) * a[ 4]
+ + ((int128_t)a[ 1]) * a[ 3]) * 2
+ + ((int128_t)a[ 2]) * a[ 2];
+ int128_t t5 = (((int128_t)a[ 1]) * a[ 4]
+ + ((int128_t)a[ 2]) * a[ 3]) * 2;
+ int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2
+ + ((int128_t)a[ 3]) * a[ 3];
+ int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2;
+ int128_t t8 = ((int128_t)a[ 4]) * a[ 4];
+
+ t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffL;
+ t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffL;
+ t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffL;
+ t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffL;
+ t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffL;
+ t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffL;
+ t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffL;
+ t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffL;
+ r[9] = (sp_digit)(t8 >> 52);
+ r[8] = t8 & 0xfffffffffffffL;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ r[i] = a[i] + b[i];
+ }
+
+ return 0;
+}
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ r[ 0] = a[ 0] + b[ 0];
+ r[ 1] = a[ 1] + b[ 1];
+ r[ 2] = a[ 2] + b[ 2];
+ r[ 3] = a[ 3] + b[ 3];
+ r[ 4] = a[ 4] + b[ 4];
+
+ return 0;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ r[i] = a[i] - b[i];
+ }
+
+ return 0;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ r[ 0] = a[ 0] - b[ 0];
+ r[ 1] = a[ 1] - b[ 1];
+ r[ 2] = a[ 2] - b[ 2];
+ r[ 3] = a[ 3] - b[ 3];
+ r[ 4] = a[ 4] - b[ 4];
+
+ return 0;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_5(void* heap, sp_point_256* sp,
+ sp_point_256** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_256_point_free_5(sp_point_256* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 52
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 52
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xfffffffffffffL;
+ s = 52U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 52U) <= (word32)DIGIT_BIT) {
+ s += 52U;
+ r[j] &= 0xfffffffffffffL;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 52) {
+ r[j] &= 0xfffffffffffffL;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 52 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_256.
+ *
+ * p Point of type sp_point_256 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_256_point_from_ecc_point_5(sp_point_256* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_256_from_mp(p->x, 5, pm->x);
+ sp_256_from_mp(p->y, 5, pm->y);
+ sp_256_from_mp(p->z, 5, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_256_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 52
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 5);
+ r->used = 5;
+ mp_clamp(r);
+#elif DIGIT_BIT < 52
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 5; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 52) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 52 - s;
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 5; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 52 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 52 - s;
+ }
+ else {
+ s += 52;
+ }
+ }
+ r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_256 to type ecc_point.
+ *
+ * p Point of type sp_point_256.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_256_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
#define sp_256_mont_reduce_order_5 sp_256_mont_reduce_5
/* Compare a with b in constant time.
@@ -13249,87 +13344,13 @@ static void sp_256_mont_reduce_5(sp_digit* a, const sp_digit* m, sp_digit mp)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_256_mont_mul_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_256_mul_5(r, a, b);
sp_256_mont_reduce_5(r, m, mp);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
-{
- int i, j, k;
- int128_t c;
-
- c = ((int128_t)a[4]) * a[4];
- r[9] = (sp_digit)(c >> 52);
- c = (c & 0xfffffffffffffL) << 52;
- for (k = 7; k >= 0; k--) {
- for (i = 4; i >= 0; i--) {
- j = k - i;
- if (j >= 5 || i <= j) {
- break;
- }
- if (j < 0) {
- continue;
- }
-
- c += ((int128_t)a[i]) * a[j] * 2;
- }
- if (i == j) {
- c += ((int128_t)a[i]) * a[i];
- }
-
- r[k + 2] += (sp_digit)(c >> 104);
- r[k + 1] = (sp_digit)((c >> 52) & 0xfffffffffffffL);
- c = (c & 0xfffffffffffffL) << 52;
- }
- r[0] = (sp_digit)(c >> 52);
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
-{
- int128_t t0 = ((int128_t)a[ 0]) * a[ 0];
- int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2;
- int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2
- + ((int128_t)a[ 1]) * a[ 1];
- int128_t t3 = (((int128_t)a[ 0]) * a[ 3]
- + ((int128_t)a[ 1]) * a[ 2]) * 2;
- int128_t t4 = (((int128_t)a[ 0]) * a[ 4]
- + ((int128_t)a[ 1]) * a[ 3]) * 2
- + ((int128_t)a[ 2]) * a[ 2];
- int128_t t5 = (((int128_t)a[ 1]) * a[ 4]
- + ((int128_t)a[ 2]) * a[ 3]) * 2;
- int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2
- + ((int128_t)a[ 3]) * a[ 3];
- int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2;
- int128_t t8 = ((int128_t)a[ 4]) * a[ 4];
-
- t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffL;
- t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffL;
- t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffL;
- t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffL;
- t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffL;
- t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffL;
- t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffL;
- t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffL;
- r[9] = (sp_digit)(t8 >> 52);
- r[8] = t8 & 0xfffffffffffffL;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -13337,8 +13358,8 @@ SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_256_mont_sqr_5(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_256_mont_sqr_5(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_256_sqr_5(r, a);
sp_256_mont_reduce_5(r, m, mp);
@@ -13362,7 +13383,7 @@ static void sp_256_mont_sqr_n_5(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint64_t p256_mod_minus_2[4] = {
@@ -13446,7 +13467,8 @@ static void sp_256_mont_inv_5(sp_digit* r, const sp_digit* a, sp_digit* td)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_5(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_5(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*5;
@@ -13482,44 +13504,6 @@ static void sp_256_map_5(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 5; i++) {
- r[i] = a[i] + b[i];
- }
-
- return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- r[ 0] = a[ 0] + b[ 0];
- r[ 1] = a[ 1] + b[ 1];
- r[ 2] = a[ 2] + b[ 2];
- r[ 3] = a[ 3] + b[ 3];
- r[ 4] = a[ 4] + b[ 4];
-
- return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -13572,45 +13556,6 @@ static void sp_256_mont_tpl_5(sp_digit* r, const sp_digit* a, const sp_digit* m)
sp_256_norm_5(r);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- int i;
-
- for (i = 0; i < 5; i++) {
- r[i] = a[i] - b[i];
- }
-
- return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- r[ 0] = a[ 0] - b[ 0];
- r[ 1] = a[ 1] - b[ 1];
- r[ 2] = a[ 2] - b[ 2];
- r[ 3] = a[ 3] - b[ 3];
- r[ 4] = a[ 4] - b[ 4];
-
- return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -13658,13 +13603,13 @@ static void sp_256_mont_sub_5(sp_digit* r, const sp_digit* a, const sp_digit* b,
* r Result of shift.
* a Number to shift.
*/
-SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, sp_digit* a)
+SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, const sp_digit* a)
{
#ifdef WOLFSSL_SP_SMALL
int i;
for (i=0; i<4; i++) {
- r[i] = ((a[i] >> 1) + (a[i + 1] << 51)) & 0xfffffffffffffL;
+ r[i] = (a[i] >> 1) + ((a[i + 1] << 51) & 0xfffffffffffffL);
}
#else
r[0] = (a[0] >> 1) + ((a[1] << 51) & 0xfffffffffffffL);
@@ -14106,8 +14051,8 @@ static int sp_256_proj_point_add_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_5(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -14193,10 +14138,133 @@ static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, cons
}
}
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_256_mod_mul_norm_5(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ int64_t* td;
+#else
+ int64_t td[8];
+ int64_t a32d[8];
+#endif
+ int64_t* t;
+ int64_t* a32;
+ int64_t o;
+ int err = MP_OKAY;
+
+ (void)m;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
+ if (td == NULL) {
+ return MEMORY_E;
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ a32 = td + 8;
+#else
+ t = td;
+ a32 = a32d;
+#endif
+
+ a32[0] = (sp_digit)(a[0]) & 0xffffffffL;
+ a32[1] = (sp_digit)(a[0] >> 32U);
+ a32[1] |= (sp_digit)(a[1] << 20U);
+ a32[1] &= 0xffffffffL;
+ a32[2] = (sp_digit)(a[1] >> 12U) & 0xffffffffL;
+ a32[3] = (sp_digit)(a[1] >> 44U);
+ a32[3] |= (sp_digit)(a[2] << 8U);
+ a32[3] &= 0xffffffffL;
+ a32[4] = (sp_digit)(a[2] >> 24U);
+ a32[4] |= (sp_digit)(a[3] << 28U);
+ a32[4] &= 0xffffffffL;
+ a32[5] = (sp_digit)(a[3] >> 4U) & 0xffffffffL;
+ a32[6] = (sp_digit)(a[3] >> 36U);
+ a32[6] |= (sp_digit)(a[4] << 16U);
+ a32[6] &= 0xffffffffL;
+ a32[7] = (sp_digit)(a[4] >> 16U) & 0xffffffffL;
+
+ /* 1 1 0 -1 -1 -1 -1 0 */
+ t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
+ /* 0 1 1 0 -1 -1 -1 -1 */
+ t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
+ /* 0 0 1 1 0 -1 -1 -1 */
+ t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
+ /* -1 -1 0 2 2 1 0 -1 */
+ t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
+ /* 0 -1 -1 0 2 2 1 0 */
+ t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
+ /* 0 0 -1 -1 0 2 2 1 */
+ t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
+ /* -1 -1 0 0 0 1 3 2 */
+ t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
+ /* 1 0 -1 -1 -1 -1 0 3 */
+ t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
+
+ t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
+ t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
+ t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
+ t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
+ t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
+ t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
+ t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
+ o = t[7] >> 32U; t[7] &= 0xffffffffL;
+ t[0] += o;
+ t[3] -= o;
+ t[6] -= o;
+ t[7] += o;
+ t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
+ t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
+ t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
+ t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
+ t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
+ t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
+ t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
+
+ r[0] = t[0];
+ r[0] |= t[1] << 32U;
+ r[0] &= 0xfffffffffffffLL;
+ r[1] = (t[1] >> 20);
+ r[1] |= t[2] << 12U;
+ r[1] |= t[3] << 44U;
+ r[1] &= 0xfffffffffffffLL;
+ r[2] = (t[3] >> 8);
+ r[2] |= t[4] << 24U;
+ r[2] &= 0xfffffffffffffLL;
+ r[3] = (t[4] >> 28);
+ r[3] |= t[5] << 4U;
+ r[3] |= t[6] << 36U;
+ r[3] &= 0xfffffffffffffLL;
+ r[4] = (t[6] >> 16);
+ r[4] |= t[7] << 16U;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Small implementation using add and double that is cache attack resistant but
+ * allocates memory rather than use large stacks.
+ * 256 adds and doubles.
+ *
* r Resulting point.
* g Point to multiply.
* k Scalar to multiply by.
@@ -14320,8 +14388,8 @@ static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
#endif /* WOLFSSL_SP_NONBLOCK */
-static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_digit* k,
- int map, int ct, void* heap)
+static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g,
+ const sp_digit* k, int map, int ct, void* heap)
{
#ifdef WOLFSSL_SP_NO_MALLOC
sp_point_256 t[3];
@@ -14332,7 +14400,8 @@ static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_
#endif
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err = MP_OKAY;
/* Implementatio is constant time. */
@@ -14461,7 +14530,8 @@ static void sp_256_cond_copy_5(sp_digit* r, const sp_digit* a, const sp_digit m)
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*5;
@@ -14549,8 +14619,8 @@ static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n, sp_digit* t)
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256* p,
- int n, int m, sp_digit* t)
+static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r,
+ const sp_point_256* p, int n, int m, sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*5;
@@ -14561,6 +14631,7 @@ static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256*
sp_digit* y = r[(1< .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 18];
+ sp_digit vx[2 * 18];
+ sp_digit vy[2 * 18];
+ sp_digit qx_px[2 * 18];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_18(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 18 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 18 * 2;
+ vy = td + 7 * 18 * 2;
+ qx_px = td + 8 * 18 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_18(p, pm);
+ sp_1024_point_from_ecc_point_18(q, qm);
+
+ err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18);
+
+ sp_1024_mont_add_18(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 57] >> (i % 57)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_18(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_18(vx, vy, t);
+ sp_1024_proj_sqr_18(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_18(vx, vx, t);
+ sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 18, 0, sizeof(sp_digit) * 18);
+ sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_18(c, 1, NULL);
+ sp_1024_point_free_18(q, 1, NULL);
+ sp_1024_point_free_18(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_18(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 18;
+ sp_digit* rx = t + 4 * 18;
+ sp_digit* ry = t + 6 * 18;
+ sp_digit* h = t + 8 * 18;
+ sp_digit* r = t + 10 * 18;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_18(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_18(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_18(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_18(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_18(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_18(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_18(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_18(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_18(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_18(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_18(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_18(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_18(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_18(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_18(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_18(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_18(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_18(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_18(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_18(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_18(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_18(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_18(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_18(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_18(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_18(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_18(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_18(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_18(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_18(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_18(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_18(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_18(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_18(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 18;
+ sp_digit* pz2 = t + 2 * 18;
+ sp_digit* rx = t + 4 * 18;
+ sp_digit* ry = t + 6 * 18;
+ sp_digit* l = t + 8 * 18;
+ sp_digit* ty = t + 10 * 18;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_18(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_18(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_18(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_18(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_18(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_18(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_18(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_18(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_18(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_18(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_18(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_18(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_18(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_18(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_18(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_18(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_18(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_18(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_18(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_18(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_18(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_18(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_18(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_18(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_18(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[36];
+ sp_digit (*pre_vy)[36];
+ sp_digit (*pre_nvy)[36];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 18];
+ sp_digit vx[2 * 18];
+ sp_digit vy[2 * 18];
+ sp_digit pre_vx[16][36];
+ sp_digit pre_vy[16][36];
+ sp_digit pre_nvy[16][36];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_18(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 18 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 18 * 2;
+ vy = td + 7 * 18 * 2;
+ pre_vx = (sp_digit(*)[36])(td + 8 * 18 * 2);
+ pre_vy = (sp_digit(*)[36])(td + 24 * 18 * 2);
+ pre_nvy = (sp_digit(*)[36])(td + 40 * 18 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 18 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_18(p, pm);
+ sp_1024_point_from_ecc_point_18(q, qm);
+
+ err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 18);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 18);
+ sp_1024_mont_sub_18(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18);
+ sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 18);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 18);
+ sp_1024_proj_mul_18(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_18(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_18(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 18);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 18);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_18(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_18(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_18(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_18(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_18(vx, vy, t);
+ sp_1024_proj_sqr_18(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_18(vx, vx, t);
+ sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 18, 0, sizeof(sp_digit) * 18);
+ sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_18(c, 1, NULL);
+ sp_1024_point_free_18(q, 1, NULL);
+ sp_1024_point_free_18(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_18(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 18;
+ sp_digit* t2 = t + 2 * 2 * 18;
+ sp_digit* l = t + 4 * 2 * 18;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_18(l, py, p1024_mod);
+ sp_1024_mont_inv_18(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_18(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_18(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_18(t2, t1, p1024_mod);
+ sp_1024_mont_add_18(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_18(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_18(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_18(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 18);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 18);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_18(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 18;
+ sp_digit* c = t + 2 * 2 * 18;
+ sp_digit* l = t + 4 * 2 * 18;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_18(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_18(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_18(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_18(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_18(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_18(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_18(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_18(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 18);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 18);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_18(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 18;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_18(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_18(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_18(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_18(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 18];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 18 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 18 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_18(p, pm);
+
+ err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_18(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_18(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_18(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_18(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_18(c, c, t);
+ sp_1024_mont_map_18(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_18(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_18(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_18(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_18(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_18(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_18(c, c, neg, t);
+ sp_1024_mont_map_18(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_18(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_18(c, c, t);
+ sp_1024_mont_map_18(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_18(neg, 1, NULL);
+ sp_1024_point_free_18(c, 1, NULL);
+ sp_1024_point_free_18(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[36];
+ sp_digit (*pre_vy)[36];
+ sp_digit (*pre_nvy)[36];
+#else
+ sp_digit t[6 * 2 * 18];
+ sp_digit vx[2 * 18];
+ sp_digit vy[2 * 18];
+ sp_digit pre_vx[16][36];
+ sp_digit pre_vy[16][36];
+ sp_digit pre_nvy[16][36];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 18 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 18 * 2;
+ vy = td + 7 * 18 * 2;
+ pre_vx = (sp_digit(*)[36])(td + 8 * 18 * 2);
+ pre_vy = (sp_digit(*)[36])(td + 24 * 18 * 2);
+ pre_nvy = (sp_digit(*)[36])(td + 40 * 18 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_18(p, pm);
+ sp_1024_point_from_ecc_point_18(q, qm);
+
+ err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 18);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 18);
+ sp_1024_mont_sub_18(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18);
+ sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 18);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 18);
+ sp_1024_proj_mul_18(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_18(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_18(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 18);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 18);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 18);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_18(vx, vy, t);
+ sp_1024_proj_sqr_18(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_18(vx, vx, t);
+ sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 18, 0, sizeof(sp_digit) * 18);
+ sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_18(c, 1, NULL);
+ sp_1024_point_free_18(q, 1, NULL);
+ sp_1024_point_free_18(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_18(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
+ a[16] | a[17]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = n-1; i >= 0; i--) {
+ r[j] |= (((sp_digit)a[i]) << s);
+ if (s >= 49U) {
+ r[j] &= 0x1ffffffffffffffL;
+ s = 57U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ r[++j] = (sp_digit)a[i] >> s;
+ s = 8U - s;
+ }
+ else {
+ s += 8U;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_18(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*18];
+ sp_digit t2d[2*18];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int64_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 18;
+ t2 = d + 2 * 18;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_18(t1, point->y);
+ (void)sp_1024_mod_18(t1, t1, p1024_mod);
+ sp_1024_sqr_18(t2, point->x);
+ (void)sp_1024_mod_18(t2, t2, p1024_mod);
+ sp_1024_mul_18(t2, t2, point->x);
+ (void)sp_1024_mod_18(t2, t2, p1024_mod);
+ (void)sp_1024_sub_18(t2, p1024_mod, t2);
+ sp_1024_mont_add_18(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_18(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_18(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_18(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_18(t1, p1024_mod);
+ sp_1024_cond_sub_18(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_18(t1);
+ if (!sp_1024_iszero_18(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_18(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 18, pX);
+ sp_1024_from_mp(pub->y, 18, pY);
+ sp_1024_from_bin(pub->z, 18, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_18(pub, NULL);
+ }
+
+ sp_1024_point_free_18(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[18];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_18(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_18(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 18, pX);
+ sp_1024_from_mp(pub->y, 18, pY);
+ sp_1024_from_bin(pub->z, 18, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 18, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_18(pub->x) != 0) &&
+ (sp_1024_iszero_18(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_18(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_18(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_18(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_18(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_18(p->x) == 0) ||
+ (sp_1024_iszero_18(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_18(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_18(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_18(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_18(p, 0, heap);
+ sp_1024_point_free_18(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* SP_WORD_SIZE == 64 */
#endif /* !WOLFSSL_SP_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c
index 45310f711..ff357fdb5 100644
--- a/wolfcrypt/src/sp_cortexm.c
+++ b/wolfcrypt/src/sp_cortexm.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -67,7 +67,8 @@
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -109,7 +110,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -143,7 +145,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -182,7 +186,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 2048 / 8 - 1;
a[j] = 0;
@@ -1277,7 +1284,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
sp_digit a1[8];
sp_digit b1[8];
sp_digit z2[16];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_8(a1, a, &a[8]);
cb = sp_2048_add_8(b1, b, &b[8]);
@@ -1570,7 +1579,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
sp_digit a1[16];
sp_digit b1[16];
sp_digit z2[32];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_16(a1, a, &a[16]);
cb = sp_2048_add_16(b1, b, &b[16]);
@@ -2023,7 +2034,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
sp_digit a1[32];
sp_digit b1[32];
sp_digit z2[64];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_32(a1, a, &a[32]);
cb = sp_2048_add_32(b1, b, &b[32]);
@@ -2692,7 +2705,7 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -2701,7 +2714,8 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -2710,7 +2724,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -2922,8 +2936,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_32(r, a, b);
sp_2048_mont_reduce_32(r, m, mp);
@@ -2936,8 +2950,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_32(r, a);
sp_2048_mont_reduce_32(r, m, mp);
@@ -3159,7 +3173,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3225,34 +3240,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -3304,7 +3319,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3386,34 +3402,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -3444,7 +3460,7 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -3461,7 +3477,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m)
sp_2048_sub_in_place_64(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -3615,8 +3631,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_64(r, a, b);
sp_2048_mont_reduce_64(r, m, mp);
@@ -3629,8 +3645,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_64(r, a);
sp_2048_mont_reduce_64(r, m, mp);
@@ -3894,7 +3910,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3960,34 +3977,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -4039,7 +4056,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4121,34 +4139,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -4193,11 +4211,13 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[128], m[64], r[128];
+ sp_digit a[128];
+ sp_digit m[64];
+ sp_digit r[128];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -4375,9 +4395,9 @@ SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -4441,8 +4461,11 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[64 * 2];
- sp_digit p[32], q[32], dp[32];
- sp_digit tmpa[64], tmpb[64];
+ sp_digit p[32];
+ sp_digit q[32];
+ sp_digit dp[32];
+ sp_digit tmpa[64];
+ sp_digit tmpb[64];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -4539,7 +4562,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -4562,17 +4585,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 64;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -4585,14 +4610,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -4619,10 +4646,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5081,10 +5111,12 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5119,34 +5151,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_2048_lshift_64(r, norm, (byte)y);
+ sp_2048_lshift_64(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -5157,7 +5189,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_2048_mont_sqr_64(r, r, m, mp);
sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_lshift_64(r, r, (byte)y);
+ sp_2048_lshift_64(r, r, y);
sp_2048_mul_d_64(tmp, norm, r[64]);
r[64] = 0;
o = sp_2048_add_64(r, r, tmp);
@@ -5193,11 +5225,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
word32 i;
@@ -5232,6 +5266,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -5253,10 +5288,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -5293,7 +5331,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -5307,7 +5345,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -5349,7 +5388,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -5383,7 +5423,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -5422,7 +5464,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 3072 / 8 - 1;
a[j] = 0;
@@ -5920,7 +5965,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
sp_digit a1[12];
sp_digit b1[12];
sp_digit z2[24];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_12(a1, a, &a[12]);
cb = sp_3072_add_12(b1, b, &b[12]);
@@ -6293,7 +6340,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
sp_digit a1[24];
sp_digit b1[24];
sp_digit z2[48];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_24(a1, a, &a[24]);
cb = sp_3072_add_24(b1, b, &b[24]);
@@ -6906,7 +6955,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
sp_digit a1[48];
sp_digit b1[48];
sp_digit z2[96];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_3072_add_48(a1, a, &a[48]);
cb = sp_3072_add_48(b1, b, &b[48]);
@@ -7589,7 +7640,7 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -7598,7 +7649,8 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -7607,7 +7659,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -7819,8 +7871,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_48(r, a, b);
sp_3072_mont_reduce_48(r, m, mp);
@@ -7833,8 +7885,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_48(r, a);
sp_3072_mont_reduce_48(r, m, mp);
@@ -8056,7 +8108,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -8122,34 +8175,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -8201,7 +8254,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -8283,34 +8337,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -8341,7 +8395,7 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
}
#endif /* WOLFSSL_SP_SMALL */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -8358,7 +8412,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m)
sp_3072_sub_in_place_96(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -8513,8 +8567,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_96(r, a, b);
sp_3072_mont_reduce_96(r, m, mp);
@@ -8527,8 +8581,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_96(r, a);
sp_3072_mont_reduce_96(r, m, mp);
@@ -8794,7 +8848,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -8860,34 +8915,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -8939,7 +8994,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -9021,34 +9077,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -9093,11 +9149,13 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[192], m[96], r[192];
+ sp_digit a[192];
+ sp_digit m[96];
+ sp_digit r[192];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -9275,9 +9333,9 @@ SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -9341,8 +9399,11 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[96 * 2];
- sp_digit p[48], q[48], dp[48];
- sp_digit tmpa[96], tmpb[96];
+ sp_digit p[48];
+ sp_digit q[48];
+ sp_digit dp[48];
+ sp_digit tmpa[96];
+ sp_digit tmpb[96];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -9439,7 +9500,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -9462,17 +9523,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 96;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -9485,14 +9548,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 96; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -9519,10 +9584,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -10177,10 +10245,12 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -10215,34 +10285,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_3072_lshift_96(r, norm, (byte)y);
+ sp_3072_lshift_96(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -10253,7 +10323,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
sp_3072_mont_sqr_96(r, r, m, mp);
sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_lshift_96(r, r, (byte)y);
+ sp_3072_lshift_96(r, r, y);
sp_3072_mul_d_96(tmp, norm, r[96]);
r[96] = 0;
o = sp_3072_add_96(r, r, tmp);
@@ -10289,11 +10359,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
+ sp_digit b[192];
+ sp_digit e[96];
+ sp_digit m[96];
sp_digit* r = b;
word32 i;
@@ -10328,6 +10400,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -10349,10 +10422,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -10389,7 +10465,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -10403,7 +10479,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -10445,7 +10522,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -10479,7 +10557,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -10518,7 +10598,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 4096 / 8 - 1;
a[j] = 0;
@@ -11245,7 +11328,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
sp_digit a1[64];
sp_digit b1[64];
sp_digit z2[128];
- sp_digit u, ca, cb;
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
ca = sp_2048_add_64(a1, a, &a[64]);
cb = sp_2048_add_64(b1, b, &b[64]);
@@ -11609,7 +11694,8 @@ SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -11618,7 +11704,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
/* Mul a by digit b into r. (r = a * b)
@@ -11678,7 +11764,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m)
sp_4096_sub_in_place_128(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -11832,8 +11918,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_128(r, a, b);
sp_4096_mont_reduce_128(r, m, mp);
@@ -11846,8 +11932,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_128(r, a);
sp_4096_mont_reduce_128(r, m, mp);
@@ -12113,7 +12199,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12179,34 +12266,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=4; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n <<= 4;
c = 28;
}
else if (c < 4) {
- y = (int)(n >> 28);
+ y = (byte)(n >> 28);
n = e[i--];
c = 4 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 28) & 0xf);
+ y = (byte)((n >> 28) & 0xf);
n <<= 4;
c -= 4;
}
@@ -12258,7 +12345,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -12340,34 +12428,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -12412,11 +12500,13 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit a[256], m[128], r[256];
+ sp_digit a[256];
+ sp_digit m[128];
+ sp_digit r[256];
#else
sp_digit* d = NULL;
sp_digit* a = NULL;
@@ -12595,9 +12685,9 @@ SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
sp_digit* a = NULL;
@@ -12661,8 +12751,11 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
#else
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit a[128 * 2];
- sp_digit p[64], q[64], dp[64];
- sp_digit tmpa[128], tmpb[128];
+ sp_digit p[64];
+ sp_digit q[64];
+ sp_digit dp[64];
+ sp_digit tmpa[128];
+ sp_digit tmpb[128];
#else
sp_digit* t = NULL;
sp_digit* a = NULL;
@@ -12759,7 +12852,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
XMEMSET(q, 0, sizeof(q));
XMEMSET(dp, 0, sizeof(dp));
#endif
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
return err;
}
#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
@@ -12782,17 +12875,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 128;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -12805,14 +12900,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 128; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -12839,10 +12936,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
int expBits = mp_count_bits(exp);
@@ -13693,10 +13793,12 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -13731,34 +13833,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 32 - c;
}
- sp_4096_lshift_128(r, norm, (byte)y);
+ sp_4096_lshift_128(r, norm, y);
for (; i>=0 || c>=5; ) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n <<= 5;
c = 27;
}
else if (c < 5) {
- y = (int)(n >> 27);
+ y = (byte)(n >> 27);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (32 - c));
+ y |= (byte)(n >> (32 - c));
n <<= c;
c = 32 - c;
}
else {
- y = (int)((n >> 27) & 0x1f);
+ y = (byte)((n >> 27) & 0x1f);
n <<= 5;
c -= 5;
}
@@ -13769,7 +13871,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
sp_4096_mont_sqr_128(r, r, m, mp);
sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_lshift_128(r, r, (byte)y);
+ sp_4096_lshift_128(r, r, y);
sp_4096_mul_d_128(tmp, norm, r[128]);
r[128] = 0;
o = sp_4096_add_128(r, r, tmp);
@@ -13805,11 +13907,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
+ sp_digit b[256];
+ sp_digit e[128];
+ sp_digit m[128];
sp_digit* r = b;
word32 i;
@@ -13844,6 +13948,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -13856,19 +13961,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
}
#endif /* WOLFSSL_HAVE_SP_DH */
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 8];
+ /* Y ordinate of point. */
sp_digit y[2 * 8];
+ /* Z ordinate of point. */
sp_digit z[2 * 8];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -13938,7 +14047,1056 @@ static const sp_digit p256_b[8] = {
};
#endif
-static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p)
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit tmp_arr[8];
+ sp_digit* tmp = tmp_arr;
+
+ __asm__ __volatile__ (
+ /* A[0] * B[0] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r3, r4, r6, r8\n\t"
+ "mov r5, #0\n\t"
+ "str r3, [%[tmp], #0]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * B[1] */
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adc r5, r5, r8\n\t"
+ /* A[1] * B[0] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[tmp], #4]\n\t"
+ "mov r4, #0\n\t"
+ /* A[0] * B[2] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[1] * B[1] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[2] * B[0] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[tmp], #8]\n\t"
+ "mov r5, #0\n\t"
+ /* A[0] * B[3] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[1] * B[2] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[2] * B[1] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[3] * B[0] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r3, [%[tmp], #12]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * B[4] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[1] * B[3] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[2] * B[2] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[3] * B[1] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[4] * B[0] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[tmp], #16]\n\t"
+ "mov r4, #0\n\t"
+ /* A[0] * B[5] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[1] * B[4] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[2] * B[3] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[3] * B[2] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[4] * B[1] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[5] * B[0] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[tmp], #20]\n\t"
+ "mov r5, #0\n\t"
+ /* A[0] * B[6] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[1] * B[5] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[2] * B[4] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[3] * B[3] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[4] * B[2] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[5] * B[1] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[6] * B[0] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r3, [%[tmp], #24]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * B[7] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[1] * B[6] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[2] * B[5] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[3] * B[4] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[4] * B[3] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[5] * B[2] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[6] * B[1] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[7] * B[0] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #0]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[tmp], #28]\n\t"
+ "mov r4, #0\n\t"
+ /* A[1] * B[7] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[2] * B[6] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[3] * B[5] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[4] * B[4] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[5] * B[3] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[6] * B[2] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[7] * B[1] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[r], #32]\n\t"
+ "mov r5, #0\n\t"
+ /* A[2] * B[7] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[3] * B[6] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[4] * B[5] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[5] * B[4] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[6] * B[3] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[7] * B[2] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r3, [%[r], #36]\n\t"
+ "mov r3, #0\n\t"
+ /* A[3] * B[7] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[4] * B[6] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[5] * B[5] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[6] * B[4] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[7] * B[3] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "mov r4, #0\n\t"
+ /* A[4] * B[7] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[5] * B[6] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[6] * B[5] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[7] * B[4] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "mov r5, #0\n\t"
+ /* A[5] * B[7] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[6] * B[6] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[7] * B[5] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r3, [%[r], #48]\n\t"
+ "mov r3, #0\n\t"
+ /* A[6] * B[7] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ /* A[7] * B[6] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "mov r4, #0\n\t"
+ /* A[7] * B[7] */
+ "ldr r6, [%[a], #28]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adc r3, r3, r8\n\t"
+ "str r5, [%[r], #56]\n\t"
+ "str r3, [%[r], #60]\n\t"
+ /* Transfer tmp to r */
+ "ldr r3, [%[tmp], #0]\n\t"
+ "ldr r4, [%[tmp], #4]\n\t"
+ "ldr r5, [%[tmp], #8]\n\t"
+ "ldr r6, [%[tmp], #12]\n\t"
+ "str r3, [%[r], #0]\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r3, [%[tmp], #16]\n\t"
+ "ldr r4, [%[tmp], #20]\n\t"
+ "ldr r5, [%[tmp], #24]\n\t"
+ "ldr r6, [%[tmp], #28]\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "str r5, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
+ : "memory", "r3", "r4", "r5", "r6", "r8"
+ );
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
+{
+ sp_digit tmp_arr[8];
+ sp_digit* tmp = tmp_arr;
+ __asm__ __volatile__ (
+ /* A[0] * A[0] */
+ "ldr r6, [%[a], #0]\n\t"
+ "umull r3, r4, r6, r6\n\t"
+ "mov r5, #0\n\t"
+ "str r3, [%[tmp], #0]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * A[1] */
+ "ldr r8, [%[a], #4]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adc r5, r5, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[tmp], #4]\n\t"
+ "mov r4, #0\n\t"
+ /* A[0] * A[2] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adc r3, r3, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[1] * A[1] */
+ "ldr r6, [%[a], #4]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[tmp], #8]\n\t"
+ "mov r5, #0\n\t"
+ /* A[0] * A[3] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[1] * A[2] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #8]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r3, r3, r9\n\t"
+ "adcs r4, r4, r10\n\t"
+ "adc r5, r5, r11\n\t"
+ "str r3, [%[tmp], #12]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * A[4] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[1] * A[3] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[2] * A[2] */
+ "ldr r6, [%[a], #8]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r4, r4, r9\n\t"
+ "adcs r5, r5, r10\n\t"
+ "adc r3, r3, r11\n\t"
+ "str r4, [%[tmp], #16]\n\t"
+ "mov r4, #0\n\t"
+ /* A[0] * A[5] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[1] * A[4] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[2] * A[3] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #12]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r5, r5, r9\n\t"
+ "adcs r3, r3, r10\n\t"
+ "adc r4, r4, r11\n\t"
+ "str r5, [%[tmp], #20]\n\t"
+ "mov r5, #0\n\t"
+ /* A[0] * A[6] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[1] * A[5] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[2] * A[4] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[3] * A[3] */
+ "ldr r6, [%[a], #12]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r3, r3, r9\n\t"
+ "adcs r4, r4, r10\n\t"
+ "adc r5, r5, r11\n\t"
+ "str r3, [%[tmp], #24]\n\t"
+ "mov r3, #0\n\t"
+ /* A[0] * A[7] */
+ "ldr r6, [%[a], #0]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[1] * A[6] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[2] * A[5] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[3] * A[4] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #16]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r4, r4, r9\n\t"
+ "adcs r5, r5, r10\n\t"
+ "adc r3, r3, r11\n\t"
+ "str r4, [%[tmp], #28]\n\t"
+ "mov r4, #0\n\t"
+ /* A[1] * A[7] */
+ "ldr r6, [%[a], #4]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[2] * A[6] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[3] * A[5] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[4] * A[4] */
+ "ldr r6, [%[a], #16]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r5, r5, r9\n\t"
+ "adcs r3, r3, r10\n\t"
+ "adc r4, r4, r11\n\t"
+ "str r5, [%[r], #32]\n\t"
+ "mov r5, #0\n\t"
+ /* A[2] * A[7] */
+ "ldr r6, [%[a], #8]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[3] * A[6] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[4] * A[5] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #20]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r3, r3, r9\n\t"
+ "adcs r4, r4, r10\n\t"
+ "adc r5, r5, r11\n\t"
+ "str r3, [%[r], #36]\n\t"
+ "mov r3, #0\n\t"
+ /* A[3] * A[7] */
+ "ldr r6, [%[a], #12]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r9, r10, r6, r8\n\t"
+ "mov r11, #0\n\t"
+ /* A[4] * A[6] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r9, r9, r6\n\t"
+ "adcs r10, r10, r8\n\t"
+ "adc r11, r11, #0\n\t"
+ /* A[5] * A[5] */
+ "ldr r6, [%[a], #20]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "adds r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adc r11, r11, r11\n\t"
+ "adds r4, r4, r9\n\t"
+ "adcs r5, r5, r10\n\t"
+ "adc r3, r3, r11\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "mov r4, #0\n\t"
+ /* A[4] * A[7] */
+ "ldr r6, [%[a], #16]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ /* A[5] * A[6] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r3, r3, r8\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "mov r5, #0\n\t"
+ /* A[5] * A[7] */
+ "ldr r6, [%[a], #20]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[6] * A[6] */
+ "ldr r6, [%[a], #24]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r3, [%[r], #48]\n\t"
+ "mov r3, #0\n\t"
+ /* A[6] * A[7] */
+ "ldr r6, [%[a], #24]\n\t"
+ "ldr r8, [%[a], #28]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "adc r3, r3, #0\n\t"
+ "str r4, [%[r], #52]\n\t"
+ "mov r4, #0\n\t"
+ /* A[7] * A[7] */
+ "ldr r6, [%[a], #28]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r5, r5, r6\n\t"
+ "adc r3, r3, r8\n\t"
+ "str r5, [%[r], #56]\n\t"
+ "str r3, [%[r], #60]\n\t"
+ /* Transfer tmp to r */
+ "ldr r3, [%[tmp], #0]\n\t"
+ "ldr r4, [%[tmp], #4]\n\t"
+ "ldr r5, [%[tmp], #8]\n\t"
+ "ldr r6, [%[tmp], #12]\n\t"
+ "str r3, [%[r], #0]\n\t"
+ "str r4, [%[r], #4]\n\t"
+ "str r5, [%[r], #8]\n\t"
+ "str r6, [%[r], #12]\n\t"
+ "ldr r3, [%[tmp], #16]\n\t"
+ "ldr r4, [%[tmp], #20]\n\t"
+ "ldr r5, [%[tmp], #24]\n\t"
+ "ldr r6, [%[tmp], #28]\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "str r5, [%[r], #24]\n\t"
+ "str r6, [%[r], #28]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
+ : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11"
+ );
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r8, #0\n\t"
+ "add r6, r6, #32\n\t"
+ "sub r8, r8, #1\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], r8\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, r6, #32\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "subs r5, r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "subs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp,
+ sp_point_256** p)
{
int ret = MP_OKAY;
(void)heap;
@@ -13963,6 +15121,12 @@ static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p)
#endif
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -13975,7 +15139,7 @@ static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap)
}
#else
/* Clear point data if requested. */
- if (clear != 0) {
+ if ((p != NULL) && (clear != 0)) {
XMEMSET(p, 0, sizeof(*p));
}
#endif
@@ -14234,7 +15398,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 32
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -14268,7 +15433,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -14304,7 +15471,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
* p Point of type sp_point_256 (result).
* pm Point of type ecc_point.
*/
-static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm)
+static void sp_256_point_from_ecc_point_8(sp_point_256* p,
+ const ecc_point* pm)
{
XMEMSET(p->x, 0, sizeof(p->x));
XMEMSET(p->y, 0, sizeof(p->y));
@@ -14331,17 +15499,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = 8;
mp_clamp(r);
#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 8; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 32) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -14354,14 +15524,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 8; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 32 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -15594,7 +16766,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint32_t p256_mod_minus_2[8] = {
@@ -15998,7 +17170,8 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit*
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_8(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*8;
@@ -16034,92 +17207,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r8, #0\n\t"
- "add r6, r6, #32\n\t"
- "sub r8, r8, #1\n\t"
- "\n1:\n\t"
- "adds %[c], %[c], r8\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adcs r4, r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c], %[c]\n\t"
- "add %[a], %[a], #4\n\t"
- "add %[b], %[b], #4\n\t"
- "add %[r], %[r], #4\n\t"
- "cmp %[a], r6\n\t"
-#ifdef __GNUC__
- "bne 1b\n\t"
-#else
- "bne.n 1b\n\t"
-#endif /* __GNUC__ */
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -16681,101 +17768,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d
sp_256_mont_sub_8(y, y, t2, p256_mod);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "add r6, r6, #32\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "subs r5, r5, %[c]\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "sbcs r4, r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "sbc %[c], %[c], %[c]\n\t"
- "add %[a], %[a], #4\n\t"
- "add %[b], %[b], #4\n\t"
- "add %[r], %[r], #4\n\t"
- "cmp %[a], r6\n\t"
-#ifdef __GNUC__
- "bne 1b\n\t"
-#else
- "bne.n 1b\n\t"
-#endif /* __GNUC__ */
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[b], #0]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "subs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[a], #12]\n\t"
- "ldr r6, [%[b], #8]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r5, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[b], #16]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[a], #28]\n\t"
- "ldr r6, [%[b], #24]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r5, [%[r], #28]\n\t"
- "sbc %[c], %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Compare two numbers to determine if they are equal.
* Constant time implementation.
*
@@ -16999,8 +17991,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_8(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -17155,9 +18147,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 256 doubles.
+ * 76 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -17186,7 +18180,8 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -17259,7 +18254,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
i = 6;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_256_get_point_16_8(rt, t, y);
@@ -17324,12 +18319,6 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_256 {
- sp_digit x[8];
- sp_digit y[8];
-} sp_table_entry_256;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -17338,7 +18327,8 @@ typedef struct sp_table_entry_256 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*8;
@@ -17441,6 +18431,14 @@ static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
}
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_256 {
+ sp_digit x[8];
+ sp_digit y[8];
+} sp_table_entry_256;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -17527,6 +18525,10 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 64 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -17537,12 +18539,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -17661,8 +18666,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -17684,8 +18691,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -17713,8 +18722,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=63; j<4; j++,x+=64) {
+ x = 63;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -17728,8 +18739,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=62; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=64) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 64;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -17771,16 +18784,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -17788,9 +18810,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -17899,6 +18927,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 32 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -17909,12 +18941,15 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a,
sp_table_entry_256* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_256 td, s1d, s2d;
+ sp_point_256 td;
+ sp_point_256 s1d;
+ sp_point_256 s2d;
#endif
sp_point_256* t;
sp_point_256* s1 = NULL;
sp_point_256* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -18033,8 +19068,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -18056,8 +19093,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
sp_point_256* rt;
sp_point_256* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -18085,8 +19124,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
y = 0;
- for (j=0,x=31; j<8; j++,x+=32) {
+ x = 31;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -18100,8 +19141,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
rt->infinity = !y;
for (i=30; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=32) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 32;
}
sp_256_proj_point_dbl_8(rt, rt, t);
@@ -18143,16 +19186,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_256_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[8];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[8];
+ /* Precomputation table for point. */
sp_table_entry_256 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_256_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_256_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_256_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -18160,9 +19212,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0;
static wolfSSL_Mutex sp_cache_256_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_256_inited == 0) {
@@ -18279,8 +19337,8 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -18321,7 +19379,94 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(point, gm);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 64 between points.
+ */
static const sp_table_entry_256 p256_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -18406,6 +19551,11 @@ static const sp_table_entry_256 p256_table[16] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^64, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -18421,6 +19571,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 32 between points.
+ */
static const sp_table_entry_256 p256_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -19705,6 +20859,11 @@ static const sp_table_entry_256 p256_table[256] = {
/* Multiply the base point of P256 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^32, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -19730,7 +20889,7 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 p;
@@ -19771,6 +20930,87 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P256 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_256 p;
+ sp_point_256 a;
+ sp_digit kd[8];
+ sp_digit t[8 * 2 * 5];
+#endif
+ sp_point_256* point;
+ sp_point_256* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_256_point_new_8(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_256_point_new_8(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 8;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_256_from_mp(k, 8, km);
+ sp_256_point_from_ecc_point_8(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_256_proj_point_add_8(point, point, addP, tmp);
+
+ if (map) {
+ sp_256_map_8(point, point, tmp);
+ }
+
+ err = sp_256_point_to_ecc_point_8(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_256_point_free_8(addP, 0, heap);
+ sp_256_point_free_8(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -19784,7 +21024,7 @@ static int sp_256_iszero_8(const sp_digit* a)
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -19833,7 +21073,8 @@ SP_NOINLINE static void sp_256_add_one_8(sp_digit* a)
*/
static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -19977,7 +21218,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_256_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 256 / 8 - 1;
a[j] = 0;
@@ -20018,7 +21262,7 @@ static void sp_256_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -20069,515 +21313,6 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
#endif /* HAVE_ECC_DHE */
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit tmp_arr[8];
- sp_digit* tmp = tmp_arr;
-
- __asm__ __volatile__ (
- /* A[0] * B[0] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r3, r4, r6, r8\n\t"
- "mov r5, #0\n\t"
- "str r3, [%[tmp], #0]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * B[1] */
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adc r5, r5, r8\n\t"
- /* A[1] * B[0] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[tmp], #4]\n\t"
- "mov r4, #0\n\t"
- /* A[0] * B[2] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[1] * B[1] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[2] * B[0] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[tmp], #8]\n\t"
- "mov r5, #0\n\t"
- /* A[0] * B[3] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[1] * B[2] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[2] * B[1] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[3] * B[0] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "str r3, [%[tmp], #12]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * B[4] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[1] * B[3] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[2] * B[2] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[3] * B[1] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[4] * B[0] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[tmp], #16]\n\t"
- "mov r4, #0\n\t"
- /* A[0] * B[5] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[1] * B[4] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[2] * B[3] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[3] * B[2] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[4] * B[1] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[5] * B[0] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[tmp], #20]\n\t"
- "mov r5, #0\n\t"
- /* A[0] * B[6] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[1] * B[5] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[2] * B[4] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[3] * B[3] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[4] * B[2] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[5] * B[1] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[6] * B[0] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "str r3, [%[tmp], #24]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * B[7] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[1] * B[6] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[2] * B[5] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[3] * B[4] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[4] * B[3] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[5] * B[2] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[6] * B[1] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[7] * B[0] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #0]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[tmp], #28]\n\t"
- "mov r4, #0\n\t"
- /* A[1] * B[7] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[2] * B[6] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[3] * B[5] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[4] * B[4] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[5] * B[3] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[6] * B[2] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[7] * B[1] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[r], #32]\n\t"
- "mov r5, #0\n\t"
- /* A[2] * B[7] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[3] * B[6] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[4] * B[5] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[5] * B[4] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[6] * B[3] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[7] * B[2] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "str r3, [%[r], #36]\n\t"
- "mov r3, #0\n\t"
- /* A[3] * B[7] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[4] * B[6] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[5] * B[5] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[6] * B[4] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[7] * B[3] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[r], #40]\n\t"
- "mov r4, #0\n\t"
- /* A[4] * B[7] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[5] * B[6] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[6] * B[5] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[7] * B[4] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[r], #44]\n\t"
- "mov r5, #0\n\t"
- /* A[5] * B[7] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[6] * B[6] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[7] * B[5] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "str r3, [%[r], #48]\n\t"
- "mov r3, #0\n\t"
- /* A[6] * B[7] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- /* A[7] * B[6] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[r], #52]\n\t"
- "mov r4, #0\n\t"
- /* A[7] * B[7] */
- "ldr r6, [%[a], #28]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adc r3, r3, r8\n\t"
- "str r5, [%[r], #56]\n\t"
- "str r3, [%[r], #60]\n\t"
- /* Transfer tmp to r */
- "ldr r3, [%[tmp], #0]\n\t"
- "ldr r4, [%[tmp], #4]\n\t"
- "ldr r5, [%[tmp], #8]\n\t"
- "ldr r6, [%[tmp], #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [%[tmp], #16]\n\t"
- "ldr r4, [%[tmp], #20]\n\t"
- "ldr r5, [%[tmp], #24]\n\t"
- "ldr r6, [%[tmp], #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
- : "memory", "r3", "r4", "r5", "r6", "r8"
- );
-}
-
#endif
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
#ifdef WOLFSSL_SP_SMALL
@@ -20837,357 +21572,6 @@ static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit
#endif
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
- sp_digit tmp_arr[8];
- sp_digit* tmp = tmp_arr;
- __asm__ __volatile__ (
- /* A[0] * A[0] */
- "ldr r6, [%[a], #0]\n\t"
- "umull r3, r4, r6, r6\n\t"
- "mov r5, #0\n\t"
- "str r3, [%[tmp], #0]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * A[1] */
- "ldr r8, [%[a], #4]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adc r5, r5, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[tmp], #4]\n\t"
- "mov r4, #0\n\t"
- /* A[0] * A[2] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adc r3, r3, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[1] * A[1] */
- "ldr r6, [%[a], #4]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[tmp], #8]\n\t"
- "mov r5, #0\n\t"
- /* A[0] * A[3] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[1] * A[2] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #8]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r3, r3, r9\n\t"
- "adcs r4, r4, r10\n\t"
- "adc r5, r5, r11\n\t"
- "str r3, [%[tmp], #12]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * A[4] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[1] * A[3] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[2] * A[2] */
- "ldr r6, [%[a], #8]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r4, r4, r9\n\t"
- "adcs r5, r5, r10\n\t"
- "adc r3, r3, r11\n\t"
- "str r4, [%[tmp], #16]\n\t"
- "mov r4, #0\n\t"
- /* A[0] * A[5] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[1] * A[4] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[2] * A[3] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[a], #12]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r5, r5, r9\n\t"
- "adcs r3, r3, r10\n\t"
- "adc r4, r4, r11\n\t"
- "str r5, [%[tmp], #20]\n\t"
- "mov r5, #0\n\t"
- /* A[0] * A[6] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[1] * A[5] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[2] * A[4] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[3] * A[3] */
- "ldr r6, [%[a], #12]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r3, r3, r9\n\t"
- "adcs r4, r4, r10\n\t"
- "adc r5, r5, r11\n\t"
- "str r3, [%[tmp], #24]\n\t"
- "mov r3, #0\n\t"
- /* A[0] * A[7] */
- "ldr r6, [%[a], #0]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[1] * A[6] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[2] * A[5] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[3] * A[4] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[a], #16]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r4, r4, r9\n\t"
- "adcs r5, r5, r10\n\t"
- "adc r3, r3, r11\n\t"
- "str r4, [%[tmp], #28]\n\t"
- "mov r4, #0\n\t"
- /* A[1] * A[7] */
- "ldr r6, [%[a], #4]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[2] * A[6] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[3] * A[5] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[4] * A[4] */
- "ldr r6, [%[a], #16]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r5, r5, r9\n\t"
- "adcs r3, r3, r10\n\t"
- "adc r4, r4, r11\n\t"
- "str r5, [%[r], #32]\n\t"
- "mov r5, #0\n\t"
- /* A[2] * A[7] */
- "ldr r6, [%[a], #8]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[3] * A[6] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[4] * A[5] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[a], #20]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r3, r3, r9\n\t"
- "adcs r4, r4, r10\n\t"
- "adc r5, r5, r11\n\t"
- "str r3, [%[r], #36]\n\t"
- "mov r3, #0\n\t"
- /* A[3] * A[7] */
- "ldr r6, [%[a], #12]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r9, r10, r6, r8\n\t"
- "mov r11, #0\n\t"
- /* A[4] * A[6] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r9, r9, r6\n\t"
- "adcs r10, r10, r8\n\t"
- "adc r11, r11, #0\n\t"
- /* A[5] * A[5] */
- "ldr r6, [%[a], #20]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "adds r9, r9, r9\n\t"
- "adcs r10, r10, r10\n\t"
- "adc r11, r11, r11\n\t"
- "adds r4, r4, r9\n\t"
- "adcs r5, r5, r10\n\t"
- "adc r3, r3, r11\n\t"
- "str r4, [%[r], #40]\n\t"
- "mov r4, #0\n\t"
- /* A[4] * A[7] */
- "ldr r6, [%[a], #16]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- /* A[5] * A[6] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[a], #24]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "adds r5, r5, r6\n\t"
- "adcs r3, r3, r8\n\t"
- "adc r4, r4, #0\n\t"
- "str r5, [%[r], #44]\n\t"
- "mov r5, #0\n\t"
- /* A[5] * A[7] */
- "ldr r6, [%[a], #20]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- /* A[6] * A[6] */
- "ldr r6, [%[a], #24]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, #0\n\t"
- "str r3, [%[r], #48]\n\t"
- "mov r3, #0\n\t"
- /* A[6] * A[7] */
- "ldr r6, [%[a], #24]\n\t"
- "ldr r8, [%[a], #28]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "adc r3, r3, #0\n\t"
- "str r4, [%[r], #52]\n\t"
- "mov r4, #0\n\t"
- /* A[7] * A[7] */
- "ldr r6, [%[a], #28]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r5, r5, r6\n\t"
- "adc r3, r3, r8\n\t"
- "str r5, [%[r], #56]\n\t"
- "str r3, [%[r], #60]\n\t"
- /* Transfer tmp to r */
- "ldr r3, [%[tmp], #0]\n\t"
- "ldr r4, [%[tmp], #4]\n\t"
- "ldr r5, [%[tmp], #8]\n\t"
- "ldr r6, [%[tmp], #12]\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [%[tmp], #16]\n\t"
- "ldr r4, [%[tmp], #20]\n\t"
- "ldr r5, [%[tmp], #24]\n\t"
- "ldr r6, [%[tmp], #28]\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
- : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11"
- );
-}
-
#ifdef WOLFSSL_SP_SMALL
/* Order-2 for the P256 curve. */
static const uint32_t p256_order_minus_2[8] = {
@@ -21196,7 +21580,7 @@ static const uint32_t p256_order_minus_2[8] = {
};
#else
/* The low half of the order-2 of the P256 curve. */
-static const uint32_t p256_order_low[4] = {
+static const sp_int_digit p256_order_low[4] = {
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
};
#endif /* WOLFSSL_SP_SMALL */
@@ -21342,7 +21726,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6 */
for (i=127; i>=112; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21352,7 +21736,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
for (i=107; i>=64; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21362,7 +21746,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
for (i=59; i>=32; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21372,7 +21756,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
for (i=27; i>=0; i--) {
sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_256_mont_mul_order_8(t2, t2, a);
}
}
@@ -21383,12 +21767,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_256_mul_8(k, k, p256_norm_order);
+ err = sp_256_mod_8(k, k, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(k);
+
+ /* kInv = 1/k mod order */
+ sp_256_mont_inv_order_8(kInv, k, tmp);
+ sp_256_norm_8(kInv);
+
+ /* s = r * x + e */
+ sp_256_mul_8(x, x, r);
+ err = sp_256_mod_8(x, x, p256_order);
+ }
+ if (err == MP_OKAY) {
+ sp_256_norm_8(x);
+ carry = sp_256_add_8(s, e, x);
+ sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
+ sp_256_norm_8(s);
+ c = sp_256_cmp_8(s, p256_order);
+ sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
+ sp_256_norm_8(s);
+
+ /* s = s * k^-1 mod order */
+ sp_256_mont_mul_order_8(s, s, kInv);
+ sp_256_norm_8(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 256 bits] from binary
* r = (k.G)->x mod order
@@ -21423,8 +21858,8 @@ typedef struct sp_ecc_sign_256_ctx {
int i;
} sp_ecc_sign_256_ctx;
-int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
@@ -21564,8 +21999,8 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -21583,11 +22018,9 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_256* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -21618,7 +22051,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 32U) {
hashLen = 32U;
@@ -21626,8 +22058,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_256_from_mp(x, 8, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
@@ -21637,7 +22067,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL);
+ err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -21648,38 +22078,15 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0));
sp_256_norm_8(r);
- /* Conv k to Montgomery form (mod order) */
- sp_256_mul_8(k, k, p256_norm_order);
- err = sp_256_mod_8(k, k, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(k);
- /* kInv = 1/k mod order */
- sp_256_mont_inv_order_8(kInv, k, tmp);
- sp_256_norm_8(kInv);
-
- /* s = r * x + e */
- sp_256_mul_8(x, x, r);
- err = sp_256_mod_8(x, x, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(x);
+ sp_256_from_mp(x, 8, priv);
sp_256_from_bin(e, 8, hash, (int)hashLen);
- carry = sp_256_add_8(s, e, x);
- sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
- sp_256_norm_8(s);
- c = sp_256_cmp_8(s, p256_order);
- sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
- sp_256_norm_8(s);
- /* s = s * k^-1 mod order */
- sp_256_mont_mul_order_8(s, s, kInv);
- sp_256_norm_8(s);
+ err = sp_256_calc_s_8(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_256_iszero_8(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -21707,7 +22114,6 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U);
#endif
sp_256_point_free_8(point, 1, heap);
@@ -22001,6 +22407,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2,
+ sp_digit* tmp)
+{
+
+ sp_256_proj_point_add_8(p1, p1, p2, tmp);
+ if (sp_256_iszero_8(p1->z)) {
+ if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
+ sp_256_proj_point_dbl_8(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_256_mod_inv_8(s, s, p256_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_256_mul_8(s, s, p256_norm_order);
+ }
+ err = sp_256_mod_8(s, s, p256_order);
+ if (err == MP_OKAY) {
+ sp_256_norm_8(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_256_mont_inv_order_8(s, s, tmp);
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#else
+ {
+ sp_256_mont_mul_order_8(u1, u1, s);
+ sp_256_mont_mul_order_8(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_256_add_points_8(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 256)
@@ -22019,8 +22515,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_256_ctx {
@@ -22039,8 +22534,9 @@ typedef struct sp_ecc_verify_256_ctx {
sp_point_256 p2;
} sp_ecc_verify_256_ctx;
-int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
@@ -22194,8 +22690,9 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -22214,7 +22711,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_256* p1;
sp_point_256* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_256_point_new_8(heap, p1d, p1);
@@ -22255,66 +22752,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_256_mod_inv_8(s, s, p256_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_256_mul_8(s, s, p256_norm_order);
- }
- err = sp_256_mod_8(s, s, p256_order);
+ err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_256_norm_8(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_256_mont_inv_order_8(s, s, tmp);
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#else
- {
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_256_proj_point_add_8(p1, p1, p2, tmp);
- if (sp_256_iszero_8(p1->z)) {
- if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
- sp_256_proj_point_dbl_8(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_256_from_mp(u2, 8, r);
@@ -22336,16 +22776,16 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_256_cmp_8(u2, p256_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
- p256_mp_mod);
- *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
+ p256_mp_mod);
+ *res = (sp_256_cmp_8(p1->x, u1) == 0);
}
}
}
@@ -22369,7 +22809,8 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
+static int sp_256_ecc_is_point_8(const sp_point_256* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -22432,7 +22873,7 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_256 pubd;
@@ -22466,7 +22907,8 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[8];
@@ -22520,12 +22962,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_256_cmp_8(pub->x, p256_mod) >= 0 ||
- sp_256_cmp_8(pub->y, p256_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(pub->x, p256_mod) >= 0) ||
+ (sp_256_cmp_8(pub->y, p256_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -22537,12 +22978,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_256_iszero_8(p->x) == 0) ||
- (sp_256_iszero_8(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) ||
+ (sp_256_iszero_8(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -22550,12 +22989,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_256_cmp_8(p->x, pub->x) != 0 ||
- sp_256_cmp_8(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_256_cmp_8(p->x, pub->x) != 0) ||
+ (sp_256_cmp_8(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -22745,7 +23183,7 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_256_from_mp(p->y, 8, pY);
sp_256_from_mp(p->z, 8, pZ);
- sp_256_map_8(p, p, tmp);
+ sp_256_map_8(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -22925,9 +23363,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
/* Point structure to use. */
typedef struct sp_point_384 {
+ /* X ordinate of point. */
sp_digit x[2 * 12];
+ /* Y ordinate of point. */
sp_digit y[2 * 12];
+ /* Z ordinate of point. */
sp_digit z[2 * 12];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_384;
@@ -22997,336 +23439,6 @@ static const sp_digit p384_b[12] = {
};
#endif
-static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p)
-{
- int ret = MP_OKAY;
- (void)heap;
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- (void)sp;
- *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
-#else
- *p = sp;
-#endif
- if (*p == NULL) {
- ret = MEMORY_E;
- }
- return ret;
-}
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* Allocate memory for point and return error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
-#else
-/* Set pointer to data and return no error. */
-#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
-#endif
-
-
-static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
-/* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
-#else
-/* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
-#endif
- (void)heap;
-}
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
-{
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- int64_t* t;
-#else
- int64_t t[12];
-#endif
- int64_t o;
- int err = MP_OKAY;
-
- (void)m;
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
- if (t == NULL) {
- err = MEMORY_E;
- }
-#endif
-
- if (err == MP_OKAY) {
- /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
- t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11];
- /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
- t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
- t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11];
- /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
- t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11];
- /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
- t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11];
- /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
- t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11];
- /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
- t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11];
- /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
- t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11];
- /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
- t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8];
- /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
- t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9];
- /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
- t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10];
- /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
- t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11];
-
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
- o = t[11] >> 32; t[11] &= 0xffffffff;
- t[0] += o;
- t[1] -= o;
- t[3] += o;
- t[4] += o;
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- t[8] += t[7] >> 32; t[7] &= 0xffffffff;
- t[9] += t[8] >> 32; t[8] &= 0xffffffff;
- t[10] += t[9] >> 32; t[9] &= 0xffffffff;
- t[11] += t[10] >> 32; t[10] &= 0xffffffff;
-
- r[0] = t[0];
- r[1] = t[1];
- r[2] = t[2];
- r[3] = t[3];
- r[4] = t[4];
- r[5] = t[5];
- r[6] = t[6];
- r[7] = t[7];
- r[8] = t[8];
- r[9] = t[9];
- r[10] = t[10];
- r[11] = t[11];
- }
-
-#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
- if (t != NULL)
- XFREE(t, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
- return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
-static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
-{
-#if DIGIT_BIT == 32
- int j;
-
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
-#elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#else
- int i, j = 0, s = 0;
-
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
-
- for (j++; j < size; j++) {
- r[j] = 0;
- }
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point_384.
- *
- * p Point of type sp_point_384 (result).
- * pm Point of type ecc_point.
- */
-static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm)
-{
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_384_from_mp(p->x, 12, pm->x);
- sp_384_from_mp(p->y, 12, pm->y);
- sp_384_from_mp(p->z, 12, pm->z);
- p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
-static int sp_384_to_mp(const sp_digit* a, mp_int* r)
-{
- int err;
-
- err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
-#if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
- r->used = 12;
- mp_clamp(r);
-#elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = (mp_digit)(a[i] >> s);
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = (mp_digit)(a[i] >> s);
- }
- }
- s = 32 - s;
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#else
- int i, j = 0, s = 0;
-
- r->dp[0] = 0;
- for (i = 0; i < 12; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
-#endif
- }
-
- return err;
-}
-
-/* Convert a point of type sp_point_384 to type ecc_point.
- *
- * p Point of type sp_point_384.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
-{
- int err;
-
- err = sp_384_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_384_to_mp(p->z, pm->z);
- }
-
- return err;
-}
-
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -23412,6 +23524,689 @@ SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a,
XMEMCPY(r, tmp_arr, sizeof(tmp_arr));
}
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r9, r3\n\t"
+ "mov r12, %[r]\n\t"
+ "mov r6, #96\n\t"
+ "neg r6, r6\n\t"
+ "add sp, sp, r6\n\t"
+ "mov r11, sp\n\t"
+ "mov r10, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #44\n\t"
+ "mov %[a], r9\n\t"
+ "subs %[a], %[a], r6\n\t"
+ "sbc r6, r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], %[a], r6\n\t"
+ "mov r2, r9\n\t"
+ "sub r2, r2, %[a]\n\t"
+ "add %[a], %[a], r10\n\t"
+ "add r2, r2, r10\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+#ifdef __GNUC__
+ "beq 4f\n\t"
+#else
+ "beq.n 4f\n\t"
+#endif /* __GNUC__ */
+ /* Multiply * 2: Start */
+ "ldr r6, [%[a]]\n\t"
+ "ldr r8, [r2]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Multiply * 2: Done */
+#ifdef __GNUC__
+ "bal 5f\n\t"
+#else
+ "bal.n 5f\n\t"
+#endif /* __GNUC__ */
+ "\n4:\n\t"
+ /* Square: Start */
+ "ldr r6, [%[a]]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Square: Done */
+ "\n5:\n\t"
+ "add %[a], %[a], #4\n\t"
+ "sub r2, r2, #4\n\t"
+ "mov r6, #48\n\t"
+ "add r6, r6, r10\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "beq 3f\n\t"
+#else
+ "beq.n 3f\n\t"
+#endif /* __GNUC__ */
+ "cmp %[a], r2\n\t"
+#ifdef __GNUC__
+ "bgt 3f\n\t"
+#else
+ "bgt.n 3f\n\t"
+#endif /* __GNUC__ */
+ "mov r8, r9\n\t"
+ "add r8, r8, r10\n\t"
+ "cmp %[a], r8\n\t"
+#ifdef __GNUC__
+ "ble 2b\n\t"
+#else
+ "ble.n 2b\n\t"
+#endif /* __GNUC__ */
+ "\n3:\n\t"
+ "mov %[r], r11\n\t"
+ "mov r8, r9\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r8, r8, #4\n\t"
+ "mov r9, r8\n\t"
+ "mov r6, #88\n\t"
+ "cmp r8, r6\n\t"
+#ifdef __GNUC__
+ "ble 1b\n\t"
+#else
+ "ble.n 1b\n\t"
+#endif /* __GNUC__ */
+ "mov %[a], r10\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov %[r], r12\n\t"
+ "mov %[a], r11\n\t"
+ "mov r3, #92\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "subs r3, r3, #4\n\t"
+#ifdef __GNUC__
+ "bge 4b\n\t"
+#else
+ "bge.n 4b\n\t"
+#endif /* __GNUC__ */
+ "mov r6, #96\n\t"
+ "add sp, sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r8, #0\n\t"
+ "add r6, r6, #48\n\t"
+ "sub r8, r8, #1\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], r8\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#else
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, r6, #48\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "subs r5, r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "subs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r8, [%[b], #36]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r8, [%[b], #44]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp,
+ sp_point_384** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ int64_t* t;
+#else
+ int64_t t[12];
+#endif
+ int64_t o;
+ int err = MP_OKAY;
+
+ (void)m;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+
+ if (err == MP_OKAY) {
+ /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
+ t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11];
+ /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
+ t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11];
+ /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
+ t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11];
+ /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
+ t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11];
+ /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
+ t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11];
+ /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
+ t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11];
+ /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
+ t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11];
+ /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
+ t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11];
+ /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
+ t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8];
+ /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
+ t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9];
+ /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
+ t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10];
+ /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
+ t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11];
+
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+ o = t[11] >> 32; t[11] &= 0xffffffff;
+ t[0] += o;
+ t[1] -= o;
+ t[3] += o;
+ t[4] += o;
+ t[1] += t[0] >> 32; t[0] &= 0xffffffff;
+ t[2] += t[1] >> 32; t[1] &= 0xffffffff;
+ t[3] += t[2] >> 32; t[2] &= 0xffffffff;
+ t[4] += t[3] >> 32; t[3] &= 0xffffffff;
+ t[5] += t[4] >> 32; t[4] &= 0xffffffff;
+ t[6] += t[5] >> 32; t[5] &= 0xffffffff;
+ t[7] += t[6] >> 32; t[6] &= 0xffffffff;
+ t[8] += t[7] >> 32; t[7] &= 0xffffffff;
+ t[9] += t[8] >> 32; t[8] &= 0xffffffff;
+ t[10] += t[9] >> 32; t[9] &= 0xffffffff;
+ t[11] += t[10] >> 32; t[10] &= 0xffffffff;
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+ r[3] = t[3];
+ r[4] = t[4];
+ r[5] = t[5];
+ r[6] = t[6];
+ r[7] = t[7];
+ r[8] = t[8];
+ r[9] = t[9];
+ r[10] = t[10];
+ r[11] = t[11];
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL)
+ XFREE(t, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+ return err;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_384.
+ *
+ * p Point of type sp_point_384 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_384_point_from_ecc_point_12(sp_point_384* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_384_from_mp(p->x, 12, pm->x);
+ sp_384_from_mp(p->y, 12, pm->y);
+ sp_384_from_mp(p->z, 12, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_384_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
+ r->used = 12;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 12; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_384 to type ecc_point.
+ *
+ * p Point of type sp_point_384.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_384_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -23566,137 +24361,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m,
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_384_mul_12(r, a, b);
sp_384_mont_reduce_12(r, m, mp);
}
-/* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
-SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
-{
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r9, r3\n\t"
- "mov r12, %[r]\n\t"
- "mov r6, #96\n\t"
- "neg r6, r6\n\t"
- "add sp, sp, r6\n\t"
- "mov r11, sp\n\t"
- "mov r10, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #44\n\t"
- "mov %[a], r9\n\t"
- "subs %[a], %[a], r6\n\t"
- "sbc r6, r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], %[a], r6\n\t"
- "mov r2, r9\n\t"
- "sub r2, r2, %[a]\n\t"
- "add %[a], %[a], r10\n\t"
- "add r2, r2, r10\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
-#ifdef __GNUC__
- "beq 4f\n\t"
-#else
- "beq.n 4f\n\t"
-#endif /* __GNUC__ */
- /* Multiply * 2: Start */
- "ldr r6, [%[a]]\n\t"
- "ldr r8, [r2]\n\t"
- "umull r6, r8, r6, r8\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, %[r]\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, %[r]\n\t"
- /* Multiply * 2: Done */
-#ifdef __GNUC__
- "bal 5f\n\t"
-#else
- "bal.n 5f\n\t"
-#endif /* __GNUC__ */
- "\n4:\n\t"
- /* Square: Start */
- "ldr r6, [%[a]]\n\t"
- "umull r6, r8, r6, r6\n\t"
- "adds r3, r3, r6\n\t"
- "adcs r4, r4, r8\n\t"
- "adc r5, r5, %[r]\n\t"
- /* Square: Done */
- "\n5:\n\t"
- "add %[a], %[a], #4\n\t"
- "sub r2, r2, #4\n\t"
- "mov r6, #48\n\t"
- "add r6, r6, r10\n\t"
- "cmp %[a], r6\n\t"
-#ifdef __GNUC__
- "beq 3f\n\t"
-#else
- "beq.n 3f\n\t"
-#endif /* __GNUC__ */
- "cmp %[a], r2\n\t"
-#ifdef __GNUC__
- "bgt 3f\n\t"
-#else
- "bgt.n 3f\n\t"
-#endif /* __GNUC__ */
- "mov r8, r9\n\t"
- "add r8, r8, r10\n\t"
- "cmp %[a], r8\n\t"
-#ifdef __GNUC__
- "ble 2b\n\t"
-#else
- "ble.n 2b\n\t"
-#endif /* __GNUC__ */
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r8, r9\n\t"
- "str r3, [%[r], r8]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r8, r8, #4\n\t"
- "mov r9, r8\n\t"
- "mov r6, #88\n\t"
- "cmp r8, r6\n\t"
-#ifdef __GNUC__
- "ble 1b\n\t"
-#else
- "ble.n 1b\n\t"
-#endif /* __GNUC__ */
- "mov %[a], r10\n\t"
- "str r3, [%[r], r8]\n\t"
- "mov %[r], r12\n\t"
- "mov %[a], r11\n\t"
- "mov r3, #92\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "subs r3, r3, #4\n\t"
-#ifdef __GNUC__
- "bge 4b\n\t"
-#else
- "bge.n 4b\n\t"
-#endif /* __GNUC__ */
- "mov r6, #96\n\t"
- "add sp, sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
- );
-}
-
/* Square the Montgomery form number. (r = a * a mod m)
*
* r Result of squaring.
@@ -23704,8 +24375,8 @@ SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_384_sqr_12(r, a);
sp_384_mont_reduce_12(r, m, mp);
@@ -23729,7 +24400,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P384 curve. */
static const uint32_t p384_mod_minus_2[12] = {
@@ -23882,7 +24553,8 @@ SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b)
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
+static void sp_384_map_12(sp_point_384* r, const sp_point_384* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*12;
@@ -23918,102 +24590,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t)
}
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r8, #0\n\t"
- "add r6, r6, #48\n\t"
- "sub r8, r8, #1\n\t"
- "\n1:\n\t"
- "adds %[c], %[c], r8\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adcs r4, r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c], %[c]\n\t"
- "add %[a], %[a], #4\n\t"
- "add %[b], %[b], #4\n\t"
- "add %[r], %[r], #4\n\t"
- "cmp %[a], r6\n\t"
-#ifdef __GNUC__
- "bne 1b\n\t"
-#else
- "bne.n 1b\n\t"
-#endif /* __GNUC__ */
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adds r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "ldm %[a]!, {r4, r5}\n\t"
- "ldm %[b]!, {r6, r8}\n\t"
- "adcs r4, r4, r6\n\t"
- "adcs r5, r5, r8\n\t"
- "stm %[r]!, {r4, r5}\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Add two Montgomery form numbers (r = a + b % m).
*
* r Result of addition.
@@ -24060,117 +24636,6 @@ SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const
sp_384_cond_sub_12(r, r, m, 0 - o);
}
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "add r6, r6, #48\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "subs r5, r5, %[c]\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "sbcs r4, r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "sbc %[c], %[c], %[c]\n\t"
- "add %[a], %[a], #4\n\t"
- "add %[b], %[b], #4\n\t"
- "add %[r], %[r], #4\n\t"
- "cmp %[a], r6\n\t"
-#ifdef __GNUC__
- "bne 1b\n\t"
-#else
- "bne.n 1b\n\t"
-#endif /* __GNUC__ */
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6"
- );
-
- return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
-{
- sp_digit c = 0;
-
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[b], #0]\n\t"
- "ldr r8, [%[b], #4]\n\t"
- "subs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[a], #12]\n\t"
- "ldr r6, [%[b], #8]\n\t"
- "ldr r8, [%[b], #12]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r5, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[b], #16]\n\t"
- "ldr r8, [%[b], #20]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[a], #28]\n\t"
- "ldr r6, [%[b], #24]\n\t"
- "ldr r8, [%[b], #28]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r5, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[a], #36]\n\t"
- "ldr r6, [%[b], #32]\n\t"
- "ldr r8, [%[b], #36]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #32]\n\t"
- "str r5, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[a], #44]\n\t"
- "ldr r6, [%[b], #40]\n\t"
- "ldr r8, [%[b], #44]\n\t"
- "sbcs r4, r4, r6\n\t"
- "sbcs r5, r5, r8\n\t"
- "str r4, [%[r], #40]\n\t"
- "str r5, [%[r], #44]\n\t"
- "sbc %[c], %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r8"
- );
-
- return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -24718,8 +25183,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q,
- sp_digit* t)
+static void sp_384_proj_point_add_12(sp_point_384* r,
+ const sp_point_384* p, const sp_point_384* q, sp_digit* t)
{
const sp_point_384* ap[2];
sp_point_384* rp[2];
@@ -24898,9 +25363,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Simple, smaller code size and memory size, of windowing.
- * Calculate uindow of 4 bits.
- * Only add points from table.
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 384 doubles.
+ * 108 adds.
*
* r Resulting point.
* g Point to multiply.
@@ -24929,7 +25396,8 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
sp_digit* tmp;
sp_digit n;
int i;
- int c, y;
+ int c;
+ int y;
int err;
/* Constant time used for cache attack resistance implementation. */
@@ -25002,7 +25470,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
i = 10;
n = k[i+1] << 0;
c = 28;
- y = n >> 28;
+ y = (int)(n >> 28);
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
sp_384_get_point_16_12(rt, t, y);
@@ -25067,12 +25535,6 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con
return err;
}
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_384 {
- sp_digit x[12];
- sp_digit y[12];
-} sp_table_entry_384;
-
#ifdef FP_ECC
/* Double the Montgomery form projective point p a number of times.
*
@@ -25081,7 +25543,8 @@ typedef struct sp_table_entry_384 {
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t)
+static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*12;
@@ -25184,6 +25647,14 @@ static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
}
+#endif /* FP_ECC */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_384 {
+ sp_digit x[12];
+ sp_digit y[12];
+} sp_table_entry_384;
+
+#ifdef FP_ECC
#endif /* FP_ECC */
/* Add two Montgomery form projective points. The second point has a q value of
* one.
@@ -25270,6 +25741,10 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p,
#ifdef WOLFSSL_SP_SMALL
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 96 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -25280,12 +25755,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -25420,8 +25898,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 4 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -25443,8 +25923,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -25472,8 +25954,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=95; j<4; j++,x+=96) {
+ x = 95;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -25487,8 +25971,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=94; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<4; j++,x+=96) {
+ x = i;
+ for (j=0; j<4; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 96;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -25530,16 +26016,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[16];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -25547,9 +26042,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -25658,6 +26159,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
#else
#ifdef FP_ECC
/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 8
+ * 256 entries
+ * 48 bits between
*
* a The base point.
* table Place to store generated point data.
@@ -25668,12 +26173,15 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a,
sp_table_entry_384* table, sp_digit* tmp, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_point_384 td, s1d, s2d;
+ sp_point_384 td;
+ sp_point_384 s1d;
+ sp_point_384 s2d;
#endif
sp_point_384* t;
sp_point_384* s1 = NULL;
sp_point_384* s2 = NULL;
- int i, j;
+ int i;
+ int j;
int err;
(void)heap;
@@ -25808,8 +26316,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r,
/* Multiply the point by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
- * Implementation uses striping of bits.
- * Choose bits 8 bits apart.
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
*
* r Resulting point.
* k Scalar to multiply by.
@@ -25831,8 +26341,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
sp_point_384* rt;
sp_point_384* p = NULL;
sp_digit* t;
- int i, j;
- int y, x;
+ int i;
+ int j;
+ int y;
+ int x;
int err;
(void)g;
@@ -25860,8 +26372,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
y = 0;
- for (j=0,x=47; j<8; j++,x+=48) {
+ x = 47;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
#ifndef WC_NO_CACHE_RESISTANT
if (ct) {
@@ -25875,8 +26389,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
rt->infinity = !y;
for (i=46; i>=0; i--) {
y = 0;
- for (j=0,x=i; j<8; j++,x+=48) {
+ x = i;
+ for (j=0; j<8; j++) {
y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 48;
}
sp_384_proj_point_dbl_12(rt, rt, t);
@@ -25918,16 +26434,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
#define FP_ENTRIES 16
#endif
+/* Cache entry - holds precomputation tables for a point. */
typedef struct sp_cache_384_t {
+ /* X ordinate of point that table was generated from. */
sp_digit x[12];
+ /* Y ordinate of point that table was generated from. */
sp_digit y[12];
+ /* Precomputation table for point. */
sp_table_entry_384 table[256];
+ /* Count of entries in table. */
uint32_t cnt;
+ /* Point and table set in entry. */
int set;
} sp_cache_384_t;
+/* Cache of tables. */
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
+/* Index of last entry in cache. */
static THREAD_LS_T int sp_cache_384_last = -1;
+/* Cache has been initialized. */
static THREAD_LS_T int sp_cache_384_inited = 0;
#ifndef HAVE_THREAD_LS
@@ -25935,9 +26460,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0;
static wolfSSL_Mutex sp_cache_384_lock;
#endif
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
{
- int i, j;
+ int i;
+ int j;
uint32_t least;
if (sp_cache_384_inited == 0) {
@@ -26054,8 +26585,8 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
+int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
+ int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -26096,7 +26627,94 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map,
return err;
}
+/* Multiply the point by the scalar, add point a and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * p Point to multiply.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
+ const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* k = NULL;
+ sp_digit* tmp = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(point, gm);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#ifdef WOLFSSL_SP_SMALL
+/* Striping precomputation table.
+ * 4 points combined into a table of 16 points.
+ * Distance of 96 between points.
+ */
static const sp_table_entry_384 p384_table[16] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -26181,6 +26799,11 @@ static const sp_table_entry_384 p384_table[16] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^96, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -26196,6 +26819,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
}
#else
+/* Striping precomputation table.
+ * 8 points combined into a table of 256 points.
+ * Distance of 48 between points.
+ */
static const sp_table_entry_384 p384_table[256] = {
/* 0 */
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -27480,6 +28107,11 @@ static const sp_table_entry_384 p384_table[256] = {
/* Multiply the base point of P384 by the scalar and return the result.
* If map is true then convert result to affine coordinates.
*
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^48, ...
+ * Pre-generated: products of all combinations of above.
+ * 8 doubles and adds (with qz=1)
+ *
* r Resulting point.
* k Scalar to multiply by.
* map Indicates whether to convert result to affine.
@@ -27505,7 +28137,7 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
* heap Heap to use for allocation.
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
+int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 p;
@@ -27546,6 +28178,87 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap)
return err;
}
+/* Multiply the base point of P384 by the scalar, add point a and return
+ * the result. If map is true then convert result to affine coordinates.
+ *
+ * km Scalar to multiply by.
+ * am Point to add to scalar mulitply result.
+ * inMont Point to add is in montogmery form.
+ * r Resulting point.
+ * map Indicates whether to convert result to affine.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
+ int inMont, ecc_point* r, int map, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_384 p;
+ sp_point_384 a;
+ sp_digit kd[12];
+ sp_digit t[12 * 2 * 6];
+#endif
+ sp_point_384* point;
+ sp_point_384* addP = NULL;
+ sp_digit* tmp = NULL;
+ sp_digit* k = NULL;
+ int err = MP_OKAY;
+
+ err = sp_384_point_new_12(heap, p, point);
+ if (err == MP_OKAY) {
+ err = sp_384_point_new_12(heap, a, addP);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ k = (sp_digit*)XMALLOC(sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, DYNAMIC_TYPE_ECC);
+ if (k == NULL) {
+ err = MEMORY_E;
+ }
+ else {
+ tmp = k + 12;
+ }
+ }
+#else
+ k = kd;
+ tmp = t;
+#endif
+ if (err == MP_OKAY) {
+ sp_384_from_mp(k, 12, km);
+ sp_384_point_from_ecc_point_12(addP, am);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
+ }
+ if ((err == MP_OKAY) && (!inMont)) {
+ err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap);
+ }
+ if (err == MP_OKAY) {
+ sp_384_proj_point_add_12(point, point, addP, tmp);
+
+ if (map) {
+ sp_384_map_12(point, point, tmp);
+ }
+
+ err = sp_384_point_to_ecc_point_12(point, r);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (k != NULL) {
+ XFREE(k, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_384_point_free_12(addP, 0, heap);
+ sp_384_point_free_12(point, 0, heap);
+
+ return err;
+}
+
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
defined(HAVE_ECC_VERIFY)
/* Returns 1 if the number of zero.
@@ -27560,7 +28273,7 @@ static int sp_384_iszero_12(const sp_digit* a)
a[8] | a[9] | a[10] | a[11]) == 0;
}
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
/* Add 1 to a. (a = a + 1)
*
* a A single precision integer.
@@ -27621,7 +28334,8 @@ SP_NOINLINE static void sp_384_add_one_12(sp_digit* a)
*/
static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
{
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -27765,7 +28479,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
*/
static void sp_384_to_bin(sp_digit* r, byte* a)
{
- int i, j, s = 0, b;
+ int i;
+ int j;
+ int s = 0;
+ int b;
j = 384 / 8 - 1;
a[j] = 0;
@@ -27806,7 +28523,7 @@ static void sp_384_to_bin(sp_digit* r, byte* a)
* returns BUFFER_E if the buffer is to small for output size,
* MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
-int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out,
+int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
word32* outLen, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
@@ -28140,7 +28857,6 @@ static const uint32_t p384_order_minus_2[12] = {
/* The low half of the order-2 of the P384 curve. */
static const uint32_t p384_order_low[6] = {
0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
-
};
#endif /* WOLFSSL_SP_SMALL */
@@ -28288,7 +29004,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
sp_384_mont_mul_order_12(t2, t2, t);
for (i=191; i>=1; i--) {
sp_384_mont_sqr_order_12(t2, t2);
- if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
+ if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
sp_384_mont_mul_order_12(t2, t2, a);
}
}
@@ -28297,12 +29013,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
#endif /* WOLFSSL_SP_SMALL */
}
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
+#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
#ifdef HAVE_ECC_SIGN
#ifndef SP_ECC_MAX_SIG_GEN
#define SP_ECC_MAX_SIG_GEN 64
#endif
+/* Calculate second signature value S from R, k and private value.
+ *
+ * s = (r * x + e) / k
+ *
+ * s Signature value.
+ * r First signature value.
+ * k Ephemeral private key.
+ * x Private key as a number.
+ * e Hash of message as a number.
+ * tmp Temporary storage for intermediate numbers.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k,
+ sp_digit* x, const sp_digit* e, sp_digit* tmp)
+{
+ int err;
+ sp_digit carry;
+ int32_t c;
+ sp_digit* kInv = k;
+
+ /* Conv k to Montgomery form (mod order) */
+ sp_384_mul_12(k, k, p384_norm_order);
+ err = sp_384_mod_12(k, k, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(k);
+
+ /* kInv = 1/k mod order */
+ sp_384_mont_inv_order_12(kInv, k, tmp);
+ sp_384_norm_12(kInv);
+
+ /* s = r * x + e */
+ sp_384_mul_12(x, x, r);
+ err = sp_384_mod_12(x, x, p384_order);
+ }
+ if (err == MP_OKAY) {
+ sp_384_norm_12(x);
+ carry = sp_384_add_12(s, e, x);
+ sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
+ sp_384_norm_12(s);
+ c = sp_384_cmp_12(s, p384_order);
+ sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
+ sp_384_norm_12(s);
+
+ /* s = s * k^-1 mod order */
+ sp_384_mont_mul_order_12(s, s, kInv);
+ sp_384_norm_12(s);
+ }
+
+ return err;
+}
+
/* Sign the hash using the private key.
* e = [hash, 384 bits] from binary
* r = (k.G)->x mod order
@@ -28337,8 +29104,8 @@ typedef struct sp_ecc_sign_384_ctx {
int i;
} sp_ecc_sign_384_ctx;
-int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
+ mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
@@ -28478,8 +29245,8 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
+int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
+ const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -28497,11 +29264,9 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_digit* r = NULL;
sp_digit* tmp = NULL;
sp_point_384* point = NULL;
- sp_digit carry;
sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err = MP_OKAY;
int32_t c;
+ int err = MP_OKAY;
int i;
(void)heap;
@@ -28532,7 +29297,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
tmp = td;
#endif
s = e;
- kInv = k;
if (hashLen > 48U) {
hashLen = 48U;
@@ -28540,8 +29304,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
}
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_384_from_mp(x, 12, priv);
-
/* New random point. */
if (km == NULL || mp_iszero(km)) {
err = sp_384_ecc_gen_k_12(rng, k);
@@ -28551,7 +29313,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_zero(km);
}
if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL);
+ err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap);
}
if (err == MP_OKAY) {
@@ -28562,38 +29324,15 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0));
sp_384_norm_12(r);
- /* Conv k to Montgomery form (mod order) */
- sp_384_mul_12(k, k, p384_norm_order);
- err = sp_384_mod_12(k, k, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(k);
- /* kInv = 1/k mod order */
- sp_384_mont_inv_order_12(kInv, k, tmp);
- sp_384_norm_12(kInv);
-
- /* s = r * x + e */
- sp_384_mul_12(x, x, r);
- err = sp_384_mod_12(x, x, p384_order);
- }
- if (err == MP_OKAY) {
- sp_384_norm_12(x);
+ sp_384_from_mp(x, 12, priv);
sp_384_from_bin(e, 12, hash, (int)hashLen);
- carry = sp_384_add_12(s, e, x);
- sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
- sp_384_norm_12(s);
- c = sp_384_cmp_12(s, p384_order);
- sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0));
- sp_384_norm_12(s);
- /* s = s * k^-1 mod order */
- sp_384_mont_mul_order_12(s, s, kInv);
- sp_384_norm_12(s);
+ err = sp_384_calc_s_12(s, r, k, x, e, tmp);
+ }
- /* Check that signature is usable. */
- if (sp_384_iszero_12(s) == 0) {
- break;
- }
+ /* Check that signature is usable. */
+ if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) {
+ break;
}
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
i = 1;
@@ -28621,7 +29360,6 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U);
XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U);
#endif
sp_384_point_free_12(point, 1, heap);
@@ -28959,6 +29697,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
}
#endif /* WOLFSSL_SP_SMALL */
+
+/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
+ *
+ * p1 First point to add and holds result.
+ * p2 Second point to add.
+ * tmp Temporary storage for intermediate numbers.
+ */
+static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2,
+ sp_digit* tmp)
+{
+
+ sp_384_proj_point_add_12(p1, p1, p2, tmp);
+ if (sp_384_iszero_12(p1->z)) {
+ if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
+ sp_384_proj_point_dbl_12(p1, p2, tmp);
+ }
+ else {
+ /* Y ordinate is not used from here - don't set. */
+ p1->x[0] = 0;
+ p1->x[1] = 0;
+ p1->x[2] = 0;
+ p1->x[3] = 0;
+ p1->x[4] = 0;
+ p1->x[5] = 0;
+ p1->x[6] = 0;
+ p1->x[7] = 0;
+ p1->x[8] = 0;
+ p1->x[9] = 0;
+ p1->x[10] = 0;
+ p1->x[11] = 0;
+ XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
+ }
+ }
+}
+
+/* Calculate the verification point: [e/s]G + [r/s]Q
+ *
+ * p1 Calculated point.
+ * p2 Public point and temporary.
+ * s Second part of signature as a number.
+ * u1 Temporary number.
+ * u2 Temproray number.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2,
+ sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
+{
+ int err;
+
+#ifndef WOLFSSL_SP_SMALL
+ {
+ sp_384_mod_inv_12(s, s, p384_order);
+ }
+#endif /* !WOLFSSL_SP_SMALL */
+ {
+ sp_384_mul_12(s, s, p384_norm_order);
+ }
+ err = sp_384_mod_12(s, s, p384_order);
+ if (err == MP_OKAY) {
+ sp_384_norm_12(s);
+#ifdef WOLFSSL_SP_SMALL
+ {
+ sp_384_mont_inv_order_12(s, s, tmp);
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#else
+ {
+ sp_384_mont_mul_order_12(u1, u1, s);
+ sp_384_mont_mul_order_12(u2, u2, s);
+ }
+
+#endif /* WOLFSSL_SP_SMALL */
+ err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
+ p1->infinity = 1;
+ }
+ if (err == MP_OKAY) {
+ err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
+ }
+ if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
+ p2->infinity = 1;
+ }
+
+ if (err == MP_OKAY) {
+ sp_384_add_points_12(p1, p2, tmp);
+ }
+
+ return err;
+}
+
#ifdef HAVE_ECC_VERIFY
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 384)
@@ -28977,8 +29809,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
*/
#ifdef WOLFSSL_SP_NONBLOCK
typedef struct sp_ecc_verify_384_ctx {
@@ -28997,8 +29828,9 @@ typedef struct sp_ecc_verify_384_ctx {
sp_point_384 p2;
} sp_ecc_verify_384_ctx;
-int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
+ word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
+ const mp_int* r, const mp_int* sm, int* res, void* heap)
{
int err = FP_WOULDBLOCK;
sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
@@ -29152,8 +29984,9 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
+int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
+ const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm,
+ int* res, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -29172,7 +30005,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_point_384* p1;
sp_point_384* p2 = NULL;
sp_digit carry;
- int32_t c;
+ int32_t c = 0;
int err;
err = sp_384_point_new_12(heap, p1d, p1);
@@ -29213,70 +30046,9 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
sp_384_from_mp(p2->y, 12, pY);
sp_384_from_mp(p2->z, 12, pZ);
-#ifndef WOLFSSL_SP_SMALL
- {
- sp_384_mod_inv_12(s, s, p384_order);
- }
-#endif /* !WOLFSSL_SP_SMALL */
- {
- sp_384_mul_12(s, s, p384_norm_order);
- }
- err = sp_384_mod_12(s, s, p384_order);
+ err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap);
}
if (err == MP_OKAY) {
- sp_384_norm_12(s);
-#ifdef WOLFSSL_SP_SMALL
- {
- sp_384_mont_inv_order_12(s, s, tmp);
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#else
- {
- sp_384_mont_mul_order_12(u1, u1, s);
- sp_384_mont_mul_order_12(u2, u2, s);
- }
-
-#endif /* WOLFSSL_SP_SMALL */
- err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
- p1->infinity = 1;
- }
- if (err == MP_OKAY) {
- err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
- }
- if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
- p2->infinity = 1;
- }
-
- if (err == MP_OKAY) {
- {
- sp_384_proj_point_add_12(p1, p1, p2, tmp);
- if (sp_384_iszero_12(p1->z)) {
- if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
- sp_384_proj_point_dbl_12(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- p1->x[8] = 0;
- p1->x[9] = 0;
- p1->x[10] = 0;
- p1->x[11] = 0;
- XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
- }
- }
- }
-
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
sp_384_from_mp(u2, 12, r);
@@ -29298,16 +30070,16 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
/* Compare with mod and if greater or equal then not valid. */
c = sp_384_cmp_12(u2, p384_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
- p384_mp_mod);
- *res = (int)(sp_384_cmp_12(p1->x, u1) == 0);
- }
- }
+ }
+ }
+ if ((*res == 0) && (c < 0)) {
+ /* Convert to Montogomery form */
+ err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
+ if (err == MP_OKAY) {
+ /* u1 = (r + 1*order).z'.z' mod prime */
+ sp_384_mont_mul_12(u1, u2, p1->z, p384_mod,
+ p384_mp_mod);
+ *res = (sp_384_cmp_12(p1->x, u1) == 0);
}
}
}
@@ -29331,7 +30103,8 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX,
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
+static int sp_384_ecc_is_point_12(const sp_point_384* point,
+ void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
sp_digit* d = NULL;
@@ -29394,7 +30167,7 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap)
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
* not on the curve and MP_OKAY otherwise.
*/
-int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
+int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_point_384 pubd;
@@ -29428,7 +30201,8 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY)
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
* MP_OKAY otherwise.
*/
-int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
+int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit privd[12];
@@ -29482,12 +30256,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
}
}
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_384_cmp_12(pub->x, p384_mod) >= 0 ||
- sp_384_cmp_12(pub->y, p384_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(pub->x, p384_mod) >= 0) ||
+ (sp_384_cmp_12(pub->y, p384_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
}
if (err == MP_OKAY) {
@@ -29499,12 +30272,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Point * order = infinity */
err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_384_iszero_12(p->x) == 0) ||
- (sp_384_iszero_12(p->y) == 0)) {
- err = ECC_INF_E;
- }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) ||
+ (sp_384_iszero_12(p->y) == 0))) {
+ err = ECC_INF_E;
}
if (privm) {
@@ -29512,12 +30283,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
/* Base * private = point */
err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap);
}
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_384_cmp_12(p->x, pub->x) != 0 ||
- sp_384_cmp_12(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_384_cmp_12(p->x, pub->x) != 0) ||
+ (sp_384_cmp_12(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
}
}
@@ -29707,7 +30477,7 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
sp_384_from_mp(p->y, 12, pY);
sp_384_from_mp(p->z, 12, pZ);
- sp_384_map_12(p, p, tmp);
+ sp_384_map_12(p, p, tmp);
}
if (err == MP_OKAY) {
@@ -29920,6 +30690,11981 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
}
#endif
#endif /* WOLFSSL_SP_384 */
+#ifdef WOLFSSL_SP_1024
+
+/* Point structure to use. */
+typedef struct sp_point_1024 {
+ /* X ordinate of point. */
+ sp_digit x[2 * 32];
+ /* Y ordinate of point. */
+ sp_digit y[2 * 32];
+ /* Z ordinate of point. */
+ sp_digit z[2 * 32];
+ /* Indicates point is at infinity. */
+ int infinity;
+} sp_point_1024;
+
+#ifndef WOLFSSL_SP_SMALL
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit tmp_arr[16 * 2];
+ sp_digit* tmp = tmp_arr;
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r9, r3\n\t"
+ "mov r12, %[r]\n\t"
+ "mov r10, %[a]\n\t"
+ "mov r11, %[b]\n\t"
+ "mov r6, #64\n\t"
+ "add r6, r6, r10\n\t"
+ "mov r14, r6\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #60\n\t"
+ "mov %[a], r9\n\t"
+ "subs %[a], %[a], r6\n\t"
+ "sbc r6, r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], %[a], r6\n\t"
+ "mov %[b], r9\n\t"
+ "sub %[b], %[b], %[a]\n\t"
+ "add %[a], %[a], r10\n\t"
+ "add %[b], %[b], r11\n\t"
+ "\n2:\n\t"
+ /* Multiply Start */
+ "ldr r6, [%[a]]\n\t"
+ "ldr r8, [%[b]]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Multiply Done */
+ "add %[a], %[a], #4\n\t"
+ "sub %[b], %[b], #4\n\t"
+ "cmp %[a], r14\n\t"
+#ifdef __GNUC__
+ "beq 3f\n\t"
+#else
+ "beq.n 3f\n\t"
+#endif /* __GNUC__ */
+ "mov r6, r9\n\t"
+ "add r6, r6, r10\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "ble 2b\n\t"
+#else
+ "ble.n 2b\n\t"
+#endif /* __GNUC__ */
+ "\n3:\n\t"
+ "mov %[r], r12\n\t"
+ "mov r8, r9\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "add r8, r8, #4\n\t"
+ "mov r9, r8\n\t"
+ "mov r6, #120\n\t"
+ "cmp r8, r6\n\t"
+#ifdef __GNUC__
+ "ble 1b\n\t"
+#else
+ "ble.n 1b\n\t"
+#endif /* __GNUC__ */
+ "str r3, [%[r], r8]\n\t"
+ "mov %[a], r10\n\t"
+ "mov %[b], r11\n\t"
+ :
+ : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14"
+ );
+
+ XMEMCPY(r, tmp_arr, sizeof(tmp_arr));
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r9, r3\n\t"
+ "mov r12, %[r]\n\t"
+ "mov r6, #128\n\t"
+ "neg r6, r6\n\t"
+ "add sp, sp, r6\n\t"
+ "mov r11, sp\n\t"
+ "mov r10, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #60\n\t"
+ "mov %[a], r9\n\t"
+ "subs %[a], %[a], r6\n\t"
+ "sbc r6, r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], %[a], r6\n\t"
+ "mov r2, r9\n\t"
+ "sub r2, r2, %[a]\n\t"
+ "add %[a], %[a], r10\n\t"
+ "add r2, r2, r10\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+#ifdef __GNUC__
+ "beq 4f\n\t"
+#else
+ "beq.n 4f\n\t"
+#endif /* __GNUC__ */
+ /* Multiply * 2: Start */
+ "ldr r6, [%[a]]\n\t"
+ "ldr r8, [r2]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Multiply * 2: Done */
+#ifdef __GNUC__
+ "bal 5f\n\t"
+#else
+ "bal.n 5f\n\t"
+#endif /* __GNUC__ */
+ "\n4:\n\t"
+ /* Square: Start */
+ "ldr r6, [%[a]]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Square: Done */
+ "\n5:\n\t"
+ "add %[a], %[a], #4\n\t"
+ "sub r2, r2, #4\n\t"
+ "mov r6, #64\n\t"
+ "add r6, r6, r10\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "beq 3f\n\t"
+#else
+ "beq.n 3f\n\t"
+#endif /* __GNUC__ */
+ "cmp %[a], r2\n\t"
+#ifdef __GNUC__
+ "bgt 3f\n\t"
+#else
+ "bgt.n 3f\n\t"
+#endif /* __GNUC__ */
+ "mov r8, r9\n\t"
+ "add r8, r8, r10\n\t"
+ "cmp %[a], r8\n\t"
+#ifdef __GNUC__
+ "ble 2b\n\t"
+#else
+ "ble.n 2b\n\t"
+#endif /* __GNUC__ */
+ "\n3:\n\t"
+ "mov %[r], r11\n\t"
+ "mov r8, r9\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r8, r8, #4\n\t"
+ "mov r9, r8\n\t"
+ "mov r6, #120\n\t"
+ "cmp r8, r6\n\t"
+#ifdef __GNUC__
+ "ble 1b\n\t"
+#else
+ "ble.n 1b\n\t"
+#endif /* __GNUC__ */
+ "mov %[a], r10\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov %[r], r12\n\t"
+ "mov %[a], r11\n\t"
+ "mov r3, #124\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "subs r3, r3, #4\n\t"
+#ifdef __GNUC__
+ "bge 4b\n\t"
+#else
+ "bge.n 4b\n\t"
+#endif /* __GNUC__ */
+ "mov r6, #128\n\t"
+ "add sp, sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "subs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "ldm %[a], {r3, r4}\n\t"
+ "ldm %[b]!, {r5, r6}\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "stm %[a]!, {r3, r4}\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r3", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adds r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "ldm %[a]!, {r4, r5}\n\t"
+ "ldm %[b]!, {r6, r8}\n\t"
+ "adcs r4, r4, r6\n\t"
+ "adcs r5, r5, r8\n\t"
+ "stm %[r]!, {r4, r5}\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<16; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 16; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit* z0 = r;
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit b1[16];
+ sp_digit z2[32];
+ sp_digit u;
+ sp_digit ca;
+ sp_digit cb;
+
+ ca = sp_1024_add_16(a1, a, &a[16]);
+ cb = sp_1024_add_16(b1, b, &b[16]);
+ u = ca & cb;
+ sp_1024_mul_16(z1, a1, b1);
+ sp_1024_mul_16(z2, &a[16], &b[16]);
+ sp_1024_mul_16(z0, a, b);
+ sp_1024_mask_16(r + 32, a1, 0 - cb);
+ sp_1024_mask_16(b1, b1, 0 - ca);
+ u += sp_1024_add_16(r + 32, r + 32, b1);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ sp_digit* z0 = r;
+ sp_digit z2[32];
+ sp_digit z1[32];
+ sp_digit a1[16];
+ sp_digit u;
+
+ u = sp_1024_add_16(a1, a, &a[16]);
+ sp_1024_sqr_16(z1, a1);
+ sp_1024_sqr_16(z2, &a[16]);
+ sp_1024_sqr_16(z0, a);
+ sp_1024_mask_16(r + 32, a1, 0 - u);
+ u += sp_1024_add_16(r + 32, r + 32, r + 32);
+ u += sp_1024_sub_in_place_32(z1, z2);
+ u += sp_1024_sub_in_place_32(z1, z0);
+ u += sp_1024_add_32(r + 16, r + 16, z1);
+ r[48] = u;
+ XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
+ (void)sp_1024_add_32(r + 32, r + 32, z2);
+}
+
+#else
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit tmp_arr[32 * 2];
+ sp_digit* tmp = tmp_arr;
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r9, r3\n\t"
+ "mov r12, %[r]\n\t"
+ "mov r10, %[a]\n\t"
+ "mov r11, %[b]\n\t"
+ "mov r6, #128\n\t"
+ "add r6, r6, r10\n\t"
+ "mov r14, r6\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r6, #124\n\t"
+ "mov %[a], r9\n\t"
+ "subs %[a], %[a], r6\n\t"
+ "sbc r6, r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], %[a], r6\n\t"
+ "mov %[b], r9\n\t"
+ "sub %[b], %[b], %[a]\n\t"
+ "add %[a], %[a], r10\n\t"
+ "add %[b], %[b], r11\n\t"
+ "\n2:\n\t"
+ /* Multiply Start */
+ "ldr r6, [%[a]]\n\t"
+ "ldr r8, [%[b]]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Multiply Done */
+ "add %[a], %[a], #4\n\t"
+ "sub %[b], %[b], #4\n\t"
+ "cmp %[a], r14\n\t"
+#ifdef __GNUC__
+ "beq 3f\n\t"
+#else
+ "beq.n 3f\n\t"
+#endif /* __GNUC__ */
+ "mov r6, r9\n\t"
+ "add r6, r6, r10\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "ble 2b\n\t"
+#else
+ "ble.n 2b\n\t"
+#endif /* __GNUC__ */
+ "\n3:\n\t"
+ "mov %[r], r12\n\t"
+ "mov r8, r9\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "add r8, r8, #4\n\t"
+ "mov r9, r8\n\t"
+ "mov r6, #248\n\t"
+ "cmp r8, r6\n\t"
+#ifdef __GNUC__
+ "ble 1b\n\t"
+#else
+ "ble.n 1b\n\t"
+#endif /* __GNUC__ */
+ "str r3, [%[r], r8]\n\t"
+ "mov %[a], r10\n\t"
+ "mov %[b], r11\n\t"
+ :
+ : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14"
+ );
+
+ XMEMCPY(r, tmp_arr, sizeof(tmp_arr));
+}
+
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mov r4, #0\n\t"
+ "mov r5, #0\n\t"
+ "mov r9, r3\n\t"
+ "mov r12, %[r]\n\t"
+ "mov r6, #1\n\t"
+ "lsl r6, r6, #8\n\t"
+ "neg r6, r6\n\t"
+ "add sp, sp, r6\n\t"
+ "mov r11, sp\n\t"
+ "mov r10, %[a]\n\t"
+ "\n1:\n\t"
+ "mov %[r], #0\n\t"
+ "mov r6, #124\n\t"
+ "mov %[a], r9\n\t"
+ "subs %[a], %[a], r6\n\t"
+ "sbc r6, r6, r6\n\t"
+ "mvn r6, r6\n\t"
+ "and %[a], %[a], r6\n\t"
+ "mov r2, r9\n\t"
+ "sub r2, r2, %[a]\n\t"
+ "add %[a], %[a], r10\n\t"
+ "add r2, r2, r10\n\t"
+ "\n2:\n\t"
+ "cmp r2, %[a]\n\t"
+#ifdef __GNUC__
+ "beq 4f\n\t"
+#else
+ "beq.n 4f\n\t"
+#endif /* __GNUC__ */
+ /* Multiply * 2: Start */
+ "ldr r6, [%[a]]\n\t"
+ "ldr r8, [r2]\n\t"
+ "umull r6, r8, r6, r8\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Multiply * 2: Done */
+#ifdef __GNUC__
+ "bal 5f\n\t"
+#else
+ "bal.n 5f\n\t"
+#endif /* __GNUC__ */
+ "\n4:\n\t"
+ /* Square: Start */
+ "ldr r6, [%[a]]\n\t"
+ "umull r6, r8, r6, r6\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, %[r]\n\t"
+ /* Square: Done */
+ "\n5:\n\t"
+ "add %[a], %[a], #4\n\t"
+ "sub r2, r2, #4\n\t"
+ "mov r6, #128\n\t"
+ "add r6, r6, r10\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "beq 3f\n\t"
+#else
+ "beq.n 3f\n\t"
+#endif /* __GNUC__ */
+ "cmp %[a], r2\n\t"
+#ifdef __GNUC__
+ "bgt 3f\n\t"
+#else
+ "bgt.n 3f\n\t"
+#endif /* __GNUC__ */
+ "mov r8, r9\n\t"
+ "add r8, r8, r10\n\t"
+ "cmp %[a], r8\n\t"
+#ifdef __GNUC__
+ "ble 2b\n\t"
+#else
+ "ble.n 2b\n\t"
+#endif /* __GNUC__ */
+ "\n3:\n\t"
+ "mov %[r], r11\n\t"
+ "mov r8, r9\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "mov r5, #0\n\t"
+ "add r8, r8, #4\n\t"
+ "mov r9, r8\n\t"
+ "mov r6, #248\n\t"
+ "cmp r8, r6\n\t"
+#ifdef __GNUC__
+ "ble 1b\n\t"
+#else
+ "ble.n 1b\n\t"
+#endif /* __GNUC__ */
+ "mov %[a], r10\n\t"
+ "str r3, [%[r], r8]\n\t"
+ "mov %[r], r12\n\t"
+ "mov %[a], r11\n\t"
+ "mov r3, #252\n\t"
+ "\n4:\n\t"
+ "ldr r6, [%[a], r3]\n\t"
+ "str r6, [%[r], r3]\n\t"
+ "subs r3, r3, #4\n\t"
+#ifdef __GNUC__
+ "bge 4b\n\t"
+#else
+ "bge.n 4b\n\t"
+#endif /* __GNUC__ */
+ "mov r6, #1\n\t"
+ "lsl r6, r6, #8\n\t"
+ "add sp, sp, r6\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+}
+
+#endif /* !WOLFSSL_SP_SMALL */
+/* The modulus (prime) of the curve P1024. */
+static const sp_digit p1024_mod[32] = {
+ 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823,
+ 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8,
+ 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4,
+ 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27,
+ 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198,
+ 0x0a563fda,0x997abb1f
+};
+/* The Montogmery normalizer for modulus of the curve P1024. */
+static const sp_digit p1024_norm_mod[32] = {
+ 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc,
+ 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57,
+ 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b,
+ 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8,
+ 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67,
+ 0xf5a9c025,0x668544e0
+};
+/* The Montogmery multiplier for modulus of the curve P1024. */
+static sp_digit p1024_mp_mod = 0x7c8f2f3d;
+#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
+/* The order of the curve P1024. */
+static const sp_digit p1024_order[32] = {
+ 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08,
+ 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a,
+ 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd,
+ 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9,
+ 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466,
+ 0xc2958ff6,0x265eaec7
+};
+#endif
+/* The base point of curve P1024. */
+static const sp_point_1024 p1024_base = {
+ /* X ordinate */
+ {
+ 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5,
+ 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339,
+ 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7,
+ 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0,
+ 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005,
+ 0x332c29ad,0x53fc09ee,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Y ordinate */
+ {
+ 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a,
+ 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80,
+ 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c,
+ 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4,
+ 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053,
+ 0x3f6009f1,0x0a824906,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* Z ordinate */
+ {
+ 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
+ },
+ /* infinity */
+ 0
+};
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+ __asm__ __volatile__ (
+ "mov r8, %[a]\n\t"
+ "add r8, r8, #128\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "subs r5, r5, %[c]\n\t"
+ "ldr r3, [%[a]]\n\t"
+ "ldr r4, [%[a], #4]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "ldr r6, [%[b], #4]\n\t"
+ "sbcs r3, r3, r5\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "str r3, [%[a]]\n\t"
+ "str r4, [%[a], #4]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #8\n\t"
+ "add %[b], %[b], #8\n\t"
+ "cmp %[a], r8\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r3", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+SP_NOINLINE static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, sp_digit m)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r5, #128\n\t"
+ "mov r9, r5\n\t"
+ "mov r8, #0\n\t"
+ "\n1:\n\t"
+ "ldr r6, [%[b], r8]\n\t"
+ "and r6, r6, %[m]\n\t"
+ "mov r5, #0\n\t"
+ "subs r5, r5, %[c]\n\t"
+ "ldr r5, [%[a], r8]\n\t"
+ "sbcs r5, r5, r6\n\t"
+ "sbcs %[c], %[c], %[c]\n\t"
+ "str r5, [%[r], r8]\n\t"
+ "add r8, r8, #4\n\t"
+ "cmp r8, r9\n\t"
+#ifdef __GNUC__
+ "blt 1b\n\t"
+#else
+ "blt.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r5", "r6", "r8", "r9"
+ );
+
+ return c;
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "mov r8, #0\n\t"
+ "add r6, r6, #128\n\t"
+ "sub r8, r8, #1\n\t"
+ "\n1:\n\t"
+ "adds %[c], %[c], r8\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "adcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "mov %[c], #0\n\t"
+ "adc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Mul a by digit b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision digit.
+ */
+SP_NOINLINE static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a,
+ sp_digit b)
+{
+ __asm__ __volatile__ (
+ "add r9, %[a], #128\n\t"
+ /* A[0] * B */
+ "ldr r6, [%[a]], #4\n\t"
+ "umull r5, r3, r6, %[b]\n\t"
+ "mov r4, #0\n\t"
+ "str r5, [%[r]], #4\n\t"
+ /* A[0] * B - Done */
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ /* A[] * B */
+ "ldr r6, [%[a]], #4\n\t"
+ "umull r6, r8, r6, %[b]\n\t"
+ "adds r3, r3, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc r5, r5, #0\n\t"
+ /* A[] * B - Done */
+ "str r3, [%[r]], #4\n\t"
+ "mov r3, r4\n\t"
+ "mov r4, r5\n\t"
+ "cmp %[a], r9\n\t"
+#ifdef __GNUC__
+ "blt 1b\n\t"
+#else
+ "blt.n 1b\n\t"
+#endif /* __GNUC__ */
+ "str r3, [%[r]]\n\t"
+ : [r] "+r" (r), [a] "+r" (a)
+ : [b] "r" (b)
+ : "memory", "r3", "r4", "r5", "r6", "r8", "r9"
+ );
+}
+
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ *
+ * Note that this is an approximate div. It may give an answer 1 larger.
+ */
+SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+ sp_digit r = 0;
+
+ __asm__ __volatile__ (
+ "lsr r6, %[div], #16\n\t"
+ "add r6, r6, #1\n\t"
+ "udiv r4, %[d1], r6\n\t"
+ "lsl r8, r4, #16\n\t"
+ "umull r4, r5, %[div], r8\n\t"
+ "subs %[d0], %[d0], r4\n\t"
+ "sbc %[d1], %[d1], r5\n\t"
+ "udiv r5, %[d1], r6\n\t"
+ "lsl r4, r5, #16\n\t"
+ "add r8, r8, r4\n\t"
+ "umull r4, r5, %[div], r4\n\t"
+ "subs %[d0], %[d0], r4\n\t"
+ "sbc %[d1], %[d1], r5\n\t"
+ "lsl r4, %[d1], #16\n\t"
+ "orr r4, r4, %[d0], lsr #16\n\t"
+ "udiv r4, r4, r6\n\t"
+ "add r8, r8, r4\n\t"
+ "umull r4, r5, %[div], r4\n\t"
+ "subs %[d0], %[d0], r4\n\t"
+ "sbc %[d1], %[d1], r5\n\t"
+ "lsl r4, %[d1], #16\n\t"
+ "orr r4, r4, %[d0], lsr #16\n\t"
+ "udiv r4, r4, r6\n\t"
+ "add r8, r8, r4\n\t"
+ "umull r4, r5, %[div], r4\n\t"
+ "subs %[d0], %[d0], r4\n\t"
+ "sbc %[d1], %[d1], r5\n\t"
+ "udiv r4, %[d0], %[div]\n\t"
+ "add r8, r8, r4\n\t"
+ "mov %[r], r8\n\t"
+ : [r] "+r" (r)
+ : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
+ : "r4", "r5", "r6", "r8"
+ );
+ return r;
+}
+
+/* AND m into each word of a and store in r.
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * m Mask to AND against each digit.
+ */
+static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
+{
+#ifdef WOLFSSL_SP_SMALL
+ int i;
+
+ for (i=0; i<32; i++) {
+ r[i] = a[i] & m;
+ }
+#else
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ r[i+0] = a[i+0] & m;
+ r[i+1] = a[i+1] & m;
+ r[i+2] = a[i+2] & m;
+ r[i+3] = a[i+3] & m;
+ r[i+4] = a[i+4] & m;
+ r[i+5] = a[i+5] & m;
+ r[i+6] = a[i+6] & m;
+ r[i+7] = a[i+7] & m;
+ }
+#endif
+}
+
+/* Compare a with b in constant time.
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ * return -ve, 0 or +ve if a is less than, equal to or greater than b
+ * respectively.
+ */
+SP_NOINLINE static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b)
+{
+ sp_digit r = 0;
+
+
+ __asm__ __volatile__ (
+ "mov r3, #0\n\t"
+ "mvn r3, r3\n\t"
+ "mov r6, #124\n\t"
+ "\n1:\n\t"
+ "ldr r8, [%[a], r6]\n\t"
+ "ldr r5, [%[b], r6]\n\t"
+ "and r8, r8, r3\n\t"
+ "and r5, r5, r3\n\t"
+ "mov r4, r8\n\t"
+ "subs r8, r8, r5\n\t"
+ "sbc r8, r8, r8\n\t"
+ "add %[r], %[r], r8\n\t"
+ "mvn r8, r8\n\t"
+ "and r3, r3, r8\n\t"
+ "subs r5, r5, r4\n\t"
+ "sbc r8, r8, r8\n\t"
+ "sub %[r], %[r], r8\n\t"
+ "mvn r8, r8\n\t"
+ "and r3, r3, r8\n\t"
+ "sub r6, r6, #4\n\t"
+ "cmp r6, #0\n\t"
+#ifdef __GNUC__
+ "bge 1b\n\t"
+#else
+ "bge.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [r] "+r" (r)
+ : [a] "r" (a), [b] "r" (b)
+ : "r3", "r4", "r5", "r6", "r8"
+ );
+
+ return r;
+}
+
+/* Divide d in a and put remainder into r (m*d + r = a)
+ * m is not calculated as it is not needed at this time.
+ *
+ * a Number to be divided.
+ * d Number to divide with.
+ * m Multiplier result.
+ * r Remainder from the division.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m,
+ sp_digit* r)
+{
+ sp_digit t1[64], t2[33];
+ sp_digit div, r1;
+ int i;
+
+ (void)m;
+
+ div = d[31];
+ XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
+ for (i=31; i>=0; i--) {
+ sp_digit hi = t1[32 + i] - (t1[32 + i] == div);
+ r1 = div_1024_word_32(hi, t1[32 + i - 1], div);
+
+ sp_1024_mul_d_32(t2, d, r1);
+ t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2);
+ t1[32 + i] -= t2[32];
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ sp_1024_mask_32(t2, d, t1[32 + i]);
+ t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
+ }
+
+ r1 = sp_1024_cmp_32(t1, d) >= 0;
+ sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
+
+ return MP_OKAY;
+}
+
+/* Reduce a modulo m into r. (r = a mod m)
+ *
+ * r A single precision number that is the reduced result.
+ * a A single precision number that is to be reduced.
+ * m A single precision number that is the modulus to reduce with.
+ * returns MP_OKAY indicating success.
+ */
+static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ return sp_1024_div_32(a, m, NULL, r);
+}
+
+/* Multiply a number by Montogmery normalizer mod modulus (prime).
+ *
+ * r The resulting Montgomery form number.
+ * a The number to convert.
+ * m The modulus (prime).
+ * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
+ */
+static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
+{
+ sp_1024_mul_32(r, a, p1024_norm_mod);
+ return sp_1024_mod_32(r, r, m);
+}
+
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp,
+ sp_point_1024** p)
+{
+ int ret = MP_OKAY;
+ (void)heap;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ (void)sp;
+ *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
+#else
+ *p = sp;
+#endif
+ if (*p == NULL) {
+ ret = MEMORY_E;
+ }
+ return ret;
+}
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* Allocate memory for point and return error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p))
+#else
+/* Set pointer to data and return no error. */
+#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p))
+#endif
+
+
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
+static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+/* If valid pointer then clear point data if requested and free data. */
+ if (p != NULL) {
+ if (clear != 0) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+ XFREE(p, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+/* Clear point data if requested. */
+ if ((p != NULL) && (clear != 0)) {
+ XMEMSET(p, 0, sizeof(*p));
+ }
+#endif
+ (void)heap;
+}
+
+/* Convert an mp_int to an array of sp_digit.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a A multi-precision integer.
+ */
+static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
+{
+#if DIGIT_BIT == 32
+ int j;
+
+ XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
+
+ for (j = a->used; j < size; j++) {
+ r[j] = 0;
+ }
+#elif DIGIT_BIT > 32
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i] << s);
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ while ((s + 32U) <= (word32)DIGIT_BIT) {
+ s += 32U;
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ if (s < (word32)DIGIT_BIT) {
+ /* lint allow cast of mismatch word32 and mp_digit */
+ r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
+ }
+ else {
+ r[++j] = 0L;
+ }
+ }
+ s = (word32)DIGIT_BIT - s;
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r[0] = 0;
+ for (i = 0; i < a->used && j < size; i++) {
+ r[j] |= ((sp_digit)a->dp[i]) << s;
+ if (s + DIGIT_BIT >= 32) {
+ r[j] &= 0xffffffff;
+ if (j + 1 >= size) {
+ break;
+ }
+ s = 32 - s;
+ if (s == DIGIT_BIT) {
+ r[++j] = 0;
+ s = 0;
+ }
+ else {
+ r[++j] = a->dp[i] >> s;
+ s = DIGIT_BIT - s;
+ }
+ }
+ else {
+ s += DIGIT_BIT;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+#endif
+}
+
+/* Convert a point of type ecc_point to type sp_point_1024.
+ *
+ * p Point of type sp_point_1024 (result).
+ * pm Point of type ecc_point.
+ */
+static void sp_1024_point_from_ecc_point_32(sp_point_1024* p,
+ const ecc_point* pm)
+{
+ XMEMSET(p->x, 0, sizeof(p->x));
+ XMEMSET(p->y, 0, sizeof(p->y));
+ XMEMSET(p->z, 0, sizeof(p->z));
+ sp_1024_from_mp(p->x, 32, pm->x);
+ sp_1024_from_mp(p->y, 32, pm->y);
+ sp_1024_from_mp(p->z, 32, pm->z);
+ p->infinity = 0;
+}
+
+/* Convert an array of sp_digit to an mp_int.
+ *
+ * a A single precision integer.
+ * r A multi-precision integer.
+ */
+static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
+{
+ int err;
+
+ err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
+#if DIGIT_BIT == 32
+ XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
+ r->used = 32;
+ mp_clamp(r);
+#elif DIGIT_BIT < 32
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= (mp_digit)(a[i] << s);
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ s = DIGIT_BIT - s;
+ r->dp[++j] = (mp_digit)(a[i] >> s);
+ while (s + DIGIT_BIT <= 32) {
+ s += DIGIT_BIT;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ if (s == SP_WORD_SIZE) {
+ r->dp[j] = 0;
+ }
+ else {
+ r->dp[j] = (mp_digit)(a[i] >> s);
+ }
+ }
+ s = 32 - s;
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#else
+ int i;
+ int j = 0;
+ int s = 0;
+
+ r->dp[0] = 0;
+ for (i = 0; i < 32; i++) {
+ r->dp[j] |= ((mp_digit)a[i]) << s;
+ if (s + 32 >= DIGIT_BIT) {
+ #if DIGIT_BIT != 32 && DIGIT_BIT != 64
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
+ #endif
+ s = DIGIT_BIT - s;
+ r->dp[++j] = a[i] >> s;
+ s = 32 - s;
+ }
+ else {
+ s += 32;
+ }
+ }
+ r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
+ mp_clamp(r);
+#endif
+ }
+
+ return err;
+}
+
+/* Convert a point of type sp_point_1024 to type ecc_point.
+ *
+ * p Point of type sp_point_1024.
+ * pm Point of type ecc_point (result).
+ * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
+ * MP_OKAY.
+ */
+static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm)
+{
+ int err;
+
+ err = sp_1024_to_mp(p->x, pm->x);
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->y, pm->y);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_to_mp(p->z, pm->z);
+ }
+
+ return err;
+}
+
+/* Reduce the number back to 1024 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m,
+ sp_digit mp)
+{
+ sp_digit ca = 0;
+
+ __asm__ __volatile__ (
+ "mov r9, %[mp]\n\t"
+ "mov r12, %[m]\n\t"
+ "mov r10, %[a]\n\t"
+ "mov r4, #0\n\t"
+ "add r11, r10, #128\n\t"
+ "\n1:\n\t"
+ /* mu = a[i] * mp */
+ "mov %[mp], r9\n\t"
+ "ldr %[a], [r10]\n\t"
+ "mul %[mp], %[mp], %[a]\n\t"
+ "mov %[m], r12\n\t"
+ "add r14, r10, #120\n\t"
+ "\n2:\n\t"
+ /* a[i+j] += m[j] * mu */
+ "ldr %[a], [r10]\n\t"
+ "mov r5, #0\n\t"
+ /* Multiply m[j] and mu - Start */
+ "ldr r8, [%[m]], #4\n\t"
+ "umull r6, r8, %[mp], r8\n\t"
+ "adds %[a], %[a], r6\n\t"
+ "adc r5, r5, r8\n\t"
+ /* Multiply m[j] and mu - Done */
+ "adds r4, r4, %[a]\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r4, [r10], #4\n\t"
+ /* a[i+j+1] += m[j+1] * mu */
+ "ldr %[a], [r10]\n\t"
+ "mov r4, #0\n\t"
+ /* Multiply m[j] and mu - Start */
+ "ldr r8, [%[m]], #4\n\t"
+ "umull r6, r8, %[mp], r8\n\t"
+ "adds %[a], %[a], r6\n\t"
+ "adc r4, r4, r8\n\t"
+ /* Multiply m[j] and mu - Done */
+ "adds r5, r5, %[a]\n\t"
+ "adc r4, r4, #0\n\t"
+ "str r5, [r10], #4\n\t"
+ "cmp r10, r14\n\t"
+#ifdef __GNUC__
+ "blt 2b\n\t"
+#else
+ "blt.n 2b\n\t"
+#endif /* __GNUC__ */
+ /* a[i+30] += m[30] * mu */
+ "ldr %[a], [r10]\n\t"
+ "mov r5, #0\n\t"
+ /* Multiply m[j] and mu - Start */
+ "ldr r8, [%[m]], #4\n\t"
+ "umull r6, r8, %[mp], r8\n\t"
+ "adds %[a], %[a], r6\n\t"
+ "adc r5, r5, r8\n\t"
+ /* Multiply m[j] and mu - Done */
+ "adds r4, r4, %[a]\n\t"
+ "adc r5, r5, #0\n\t"
+ "str r4, [r10], #4\n\t"
+ /* a[i+31] += m[31] * mu */
+ "mov r4, %[ca]\n\t"
+ "mov %[ca], #0\n\t"
+ /* Multiply m[31] and mu - Start */
+ "ldr r8, [%[m]]\n\t"
+ "umull r6, r8, %[mp], r8\n\t"
+ "adds r5, r5, r6\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adc %[ca], %[ca], #0\n\t"
+ /* Multiply m[31] and mu - Done */
+ "ldr r6, [r10]\n\t"
+ "ldr r8, [r10, #4]\n\t"
+ "adds r6, r6, r5\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adc %[ca], %[ca], #0\n\t"
+ "str r6, [r10]\n\t"
+ "str r8, [r10, #4]\n\t"
+ /* Next word in a */
+ "sub r10, r10, #120\n\t"
+ "cmp r10, r11\n\t"
+#ifdef __GNUC__
+ "blt 1b\n\t"
+#else
+ "blt.n 1b\n\t"
+#endif /* __GNUC__ */
+ "ldr r6, [%[m]]\n\t"
+ "subs r6, r6, r8\n\t"
+ "neg %[ca], %[ca]\n\t"
+ "sbc r6, r6, r6\n\t"
+ "orr %[ca], %[ca], r6\n\t"
+ "mov %[a], r10\n\t"
+ "mov %[m], r12\n\t"
+ : [ca] "+r" (ca), [a] "+r" (a)
+ : [m] "r" (m), [mp] "r" (mp)
+ : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14"
+ );
+
+ sp_1024_cond_sub_32(a - 32, a, m, ca);
+}
+
+/* Multiply two Montogmery form numbers mod the modulus (prime).
+ * (r = a * b mod m)
+ *
+ * r Result of multiplication.
+ * a First number to multiply in Montogmery form.
+ * b Second number to multiply in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
+{
+ sp_1024_mul_32(r, a, b);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Square the Montgomery form number. (r = a * a mod m)
+ *
+ * r Result of squaring.
+ * a Number to square in Montogmery form.
+ * m Modulus (prime).
+ * mp Montogmery mulitplier.
+ */
+static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
+{
+ sp_1024_sqr_32(r, a);
+ sp_1024_mont_reduce_32(r, m, mp);
+}
+
+/* Mod-2 for the P1024 curve. */
+static const uint8_t p1024_mod_minus_2[] = {
+ 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
+ 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
+ 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
+ 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
+ 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
+ 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
+ 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
+ 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
+ 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
+ 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
+ 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
+ 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
+ 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
+ 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
+ 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
+ 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
+ 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
+ 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
+ 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
+};
+
+/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
+ * P1024 curve. (r = 1 / a mod m)
+ *
+ * r Inverse result.
+ * a Number to invert.
+ * td Temporary data.
+ */
+static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a,
+ sp_digit* td)
+{
+ sp_digit* t = td;
+ int i;
+ int j;
+ sp_digit table[32][2 * 32];
+
+ XMEMCPY(table[0], a, sizeof(sp_digit) * 32);
+ for (i = 1; i < 6; i++) {
+ sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod);
+ }
+ for (i = 1; i < 32; i++) {
+ sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
+ }
+
+ XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32);
+ for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
+ for (j = 0; j < p1024_mod_minus_2[i]; j++) {
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ }
+ sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
+ p1024_mp_mod);
+ }
+ sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod);
+}
+
+/* Normalize the values in each word to 32.
+ *
+ * a Array of sp_digit to normalize.
+ */
+#define sp_1024_norm_32(a)
+
+/* Map the Montgomery form projective coordinate point to an affine point.
+ *
+ * r Resulting affine coordinate point.
+ * p Montgomery form projective coordinate point.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p,
+ sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ int32_t n;
+
+ sp_1024_mont_inv_32(t1, p->z, t + 2*32);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ /* x /= z^2 */
+ sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U);
+ sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod);
+ /* Reduce x to less than modulus */
+ n = sp_1024_cmp_32(r->x, p1024_mod);
+ sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->x);
+
+ /* y /= z^3 */
+ sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U);
+ sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod);
+ /* Reduce y to less than modulus */
+ n = sp_1024_cmp_32(r->y, p1024_mod);
+ sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(r->y);
+
+ XMEMSET(r->z, 0, sizeof(r->z));
+ r->z[0] = 1;
+
+}
+
+/* Add two Montgomery form numbers (r = a + b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldr r14, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r14, r14, r7\n\t"
+ "neg r12, r12\n\t"
+ "sbc r14, r14, r14\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r14\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Double a Montgomery form number (r = a + a % m).
+ *
+ * r Result of doubling.
+ * a Number to double in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r4, r4, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r4, r4, r4\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r4\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Triple a Montgomery form number (r = a + a + a % m).
+ *
+ * r Result of Tripling.
+ * a Number to triple in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adds r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "adcs r4, r4, r4\n\t"
+ "adcs r5, r5, r5\n\t"
+ "adcs r6, r6, r6\n\t"
+ "adcs r7, r7, r7\n\t"
+ "adcs r8, r8, r8\n\t"
+ "adcs r9, r9, r9\n\t"
+ "adcs r10, r10, r10\n\t"
+ "adcs r14, r14, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t"
+ "ldr r4, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r4, r4, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r4, r4, r4\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r4\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "sub %[m], %[m], #128\n\t"
+ "sub %[a], %[a], #128\n\t"
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adds r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "adcs r8, r8, r4\n\t"
+ "adcs r9, r9, r5\n\t"
+ "adcs r10, r10, r6\n\t"
+ "adcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldr r7, [%[m], #124]\n\t"
+ "adc r12, r12, #0\n\t"
+ "subs r7, r7, r14\n\t"
+ "neg r12, r12\n\t"
+ "sbc r7, r7, r7\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "orr r12, r7\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "subs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbcs r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "ldm %[r], {r8, r9, r10, r14}\n\t"
+ "ldm %[m]!, {r4, r5, r6, r7}\n\t"
+ "and r4, r4, r12\n\t"
+ "and r5, r5, r12\n\t"
+ "and r6, r6, r12\n\t"
+ "and r7, r7, r12\n\t"
+ "sbcs r8, r8, r4\n\t"
+ "sbcs r9, r9, r5\n\t"
+ "sbcs r10, r10, r6\n\t"
+ "sbc r14, r14, r7\n\t"
+ "stm %[r]!, {r8, r9, r10, r14}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Subtract two Montgomery form numbers (r = a - b % m).
+ *
+ * r Result of subtration.
+ * a Number to subtract from in Montogmery form.
+ * b Number to subtract with in Montogmery form.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ const sp_digit* m)
+{
+ __asm__ __volatile__ (
+ "mov r12, #0\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "subs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[a]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[b]!, {r8, r9, r10, r14}\n\t"
+ "sbcs r4, r4, r8\n\t"
+ "sbcs r5, r5, r9\n\t"
+ "sbcs r6, r6, r10\n\t"
+ "sbcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sbc r12, r12, r12\n\t"
+ "sub %[r], %[r], #128\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adds r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adcs r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "ldm %[r], {r4, r5, r6, r7}\n\t"
+ "ldm %[m]!, {r8, r9, r10, r14}\n\t"
+ "and r8, r8, r12\n\t"
+ "and r9, r9, r12\n\t"
+ "and r10, r10, r12\n\t"
+ "and r14, r14, r12\n\t"
+ "adcs r4, r4, r8\n\t"
+ "adcs r5, r5, r9\n\t"
+ "adcs r6, r6, r10\n\t"
+ "adc r7, r7, r14\n\t"
+ "stm %[r]!, {r4, r5, r6, r7}\n\t"
+ "sub %[r], %[r], #128\n\t"
+ : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
+ :
+ : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
+ );
+}
+
+/* Conditionally add a and b using the mask m.
+ * m is -1 to add and 0 when not.
+ *
+ * r A single precision number representing conditional add result.
+ * a A single precision number to add with.
+ * b A single precision number to add.
+ * m Mask value to apply.
+ */
+SP_NOINLINE static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
+ sp_digit m)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r5, #128\n\t"
+ "mov r9, r5\n\t"
+ "mov r8, #0\n\t"
+ "\n1:\n\t"
+ "ldr r6, [%[b], r8]\n\t"
+ "and r6, r6, %[m]\n\t"
+ "adds r5, %[c], #-1\n\t"
+ "ldr r5, [%[a], r8]\n\t"
+ "adcs r5, r5, r6\n\t"
+ "mov %[c], #0\n\t"
+ "adcs %[c], %[c], %[c]\n\t"
+ "str r5, [%[r], r8]\n\t"
+ "add r8, r8, #4\n\t"
+ "cmp r8, r9\n\t"
+#ifdef __GNUC__
+ "blt 1b\n\t"
+#else
+ "blt.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c)
+ : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
+ : "memory", "r5", "r6", "r8", "r9"
+ );
+
+ return c;
+}
+
+static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a)
+{
+ __asm__ __volatile__ (
+ "ldr r2, [%[a]]\n\t"
+ "ldr r3, [%[a], #4]\n\t"
+ "lsr r2, r2, #1\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "str r2, [%[r], #0]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #12]\n\t"
+ "str r3, [%[r], #4]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #16]\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #20]\n\t"
+ "str r2, [%[r], #12]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #24]\n\t"
+ "str r3, [%[r], #16]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #28]\n\t"
+ "str r4, [%[r], #20]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "str r2, [%[r], #24]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #36]\n\t"
+ "str r3, [%[r], #28]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #40]\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #44]\n\t"
+ "str r2, [%[r], #36]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #48]\n\t"
+ "str r3, [%[r], #40]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #52]\n\t"
+ "str r4, [%[r], #44]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "str r2, [%[r], #48]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #60]\n\t"
+ "str r3, [%[r], #52]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #64]\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #68]\n\t"
+ "str r2, [%[r], #60]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #72]\n\t"
+ "str r3, [%[r], #64]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #76]\n\t"
+ "str r4, [%[r], #68]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "str r2, [%[r], #72]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #84]\n\t"
+ "str r3, [%[r], #76]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #88]\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #92]\n\t"
+ "str r2, [%[r], #84]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #96]\n\t"
+ "str r3, [%[r], #88]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #100]\n\t"
+ "str r4, [%[r], #92]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "str r2, [%[r], #96]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #108]\n\t"
+ "str r3, [%[r], #100]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #112]\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "ldr r4, [%[a], #116]\n\t"
+ "str r2, [%[r], #108]\n\t"
+ "orr r3, r3, r4, lsl #31\n\t"
+ "lsr r4, r4, #1\n\t"
+ "ldr r2, [%[a], #120]\n\t"
+ "str r3, [%[r], #112]\n\t"
+ "orr r4, r4, r2, lsl #31\n\t"
+ "lsr r2, r2, #1\n\t"
+ "ldr r3, [%[a], #124]\n\t"
+ "str r4, [%[r], #116]\n\t"
+ "orr r2, r2, r3, lsl #31\n\t"
+ "lsr r3, r3, #1\n\t"
+ "str r2, [%[r], #120]\n\t"
+ "str r3, [%[r], #124]\n\t"
+ :
+ : [r] "r" (r), [a] "r" (a)
+ : "memory", "r2", "r3", "r4"
+ );
+}
+
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+SP_NOINLINE static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+{
+ sp_digit o;
+
+ o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1));
+ sp_1024_rshift1_32(r, r);
+ r[31] |= o << 31;
+}
+
+/* Double the Montgomery form projective point p.
+ *
+ * r Result of doubling point.
+ * p Point to double.
+ * t Temporary ordinate data.
+ */
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_dbl_32_ctx {
+ int state;
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_dbl_32_ctx;
+
+static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data;
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0:
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->x = r->x;
+ ctx->y = r->y;
+ ctx->z = r->z;
+
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+ ctx->state = 1;
+ break;
+ case 1:
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 2;
+ break;
+ case 2:
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 3;
+ break;
+ case 3:
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod);
+ ctx->state = 4;
+ break;
+ case 4:
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* T2 = T2/2 */
+ sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ /* X = X - Y */
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod);
+ ctx->state = 19;
+ /* fall-through */
+ case 19:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 19) {
+ err = FP_WOULDBLOCK;
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = r->x;
+ y = r->y;
+ z = r->z;
+ /* Put infinity into result. */
+ if (r != p) {
+ r->infinity = p->infinity;
+ }
+
+ /* T1 = Z * Z */
+ sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = Y * Z */
+ sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod);
+ /* Z = 2Z */
+ sp_1024_mont_dbl_32(z, z, p1024_mod);
+ /* T2 = X - T1 */
+ sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod);
+ /* T1 = X + T1 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* T2 = T1 * T2 */
+ sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod);
+ /* T1 = 3T2 */
+ sp_1024_mont_tpl_32(t1, t2, p1024_mod);
+ /* Y = 2Y */
+ sp_1024_mont_dbl_32(y, p->y, p1024_mod);
+ /* Y = Y * Y */
+ sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod);
+ /* T2 = Y * Y */
+ sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod);
+ /* T2 = T2/2 */
+ sp_1024_div2_32(t2, t2, p1024_mod);
+ /* Y = Y * X */
+ sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod);
+ /* X = T1 * T1 */
+ sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* X = X - Y */
+ sp_1024_mont_sub_32(x, x, y, p1024_mod);
+ /* Y = Y - X */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ /* Y = Y * T1 */
+ sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod);
+ /* Y = Y - T2 */
+ sp_1024_mont_sub_32(y, y, t2, p1024_mod);
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "mov r6, %[a]\n\t"
+ "add r6, r6, #128\n\t"
+ "\n1:\n\t"
+ "mov r5, #0\n\t"
+ "subs r5, r5, %[c]\n\t"
+ "ldr r4, [%[a]]\n\t"
+ "ldr r5, [%[b]]\n\t"
+ "sbcs r4, r4, r5\n\t"
+ "str r4, [%[r]]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ "add %[a], %[a], #4\n\t"
+ "add %[b], %[b], #4\n\t"
+ "add %[r], %[r], #4\n\t"
+ "cmp %[a], r6\n\t"
+#ifdef __GNUC__
+ "bne 1b\n\t"
+#else
+ "bne.n 1b\n\t"
+#endif /* __GNUC__ */
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6"
+ );
+
+ return c;
+}
+
+#else
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b)
+{
+ sp_digit c = 0;
+
+ __asm__ __volatile__ (
+ "ldr r4, [%[a], #0]\n\t"
+ "ldr r5, [%[a], #4]\n\t"
+ "ldr r6, [%[b], #0]\n\t"
+ "ldr r8, [%[b], #4]\n\t"
+ "subs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #0]\n\t"
+ "str r5, [%[r], #4]\n\t"
+ "ldr r4, [%[a], #8]\n\t"
+ "ldr r5, [%[a], #12]\n\t"
+ "ldr r6, [%[b], #8]\n\t"
+ "ldr r8, [%[b], #12]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #8]\n\t"
+ "str r5, [%[r], #12]\n\t"
+ "ldr r4, [%[a], #16]\n\t"
+ "ldr r5, [%[a], #20]\n\t"
+ "ldr r6, [%[b], #16]\n\t"
+ "ldr r8, [%[b], #20]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #16]\n\t"
+ "str r5, [%[r], #20]\n\t"
+ "ldr r4, [%[a], #24]\n\t"
+ "ldr r5, [%[a], #28]\n\t"
+ "ldr r6, [%[b], #24]\n\t"
+ "ldr r8, [%[b], #28]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #24]\n\t"
+ "str r5, [%[r], #28]\n\t"
+ "ldr r4, [%[a], #32]\n\t"
+ "ldr r5, [%[a], #36]\n\t"
+ "ldr r6, [%[b], #32]\n\t"
+ "ldr r8, [%[b], #36]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #32]\n\t"
+ "str r5, [%[r], #36]\n\t"
+ "ldr r4, [%[a], #40]\n\t"
+ "ldr r5, [%[a], #44]\n\t"
+ "ldr r6, [%[b], #40]\n\t"
+ "ldr r8, [%[b], #44]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #40]\n\t"
+ "str r5, [%[r], #44]\n\t"
+ "ldr r4, [%[a], #48]\n\t"
+ "ldr r5, [%[a], #52]\n\t"
+ "ldr r6, [%[b], #48]\n\t"
+ "ldr r8, [%[b], #52]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #48]\n\t"
+ "str r5, [%[r], #52]\n\t"
+ "ldr r4, [%[a], #56]\n\t"
+ "ldr r5, [%[a], #60]\n\t"
+ "ldr r6, [%[b], #56]\n\t"
+ "ldr r8, [%[b], #60]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #56]\n\t"
+ "str r5, [%[r], #60]\n\t"
+ "ldr r4, [%[a], #64]\n\t"
+ "ldr r5, [%[a], #68]\n\t"
+ "ldr r6, [%[b], #64]\n\t"
+ "ldr r8, [%[b], #68]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #64]\n\t"
+ "str r5, [%[r], #68]\n\t"
+ "ldr r4, [%[a], #72]\n\t"
+ "ldr r5, [%[a], #76]\n\t"
+ "ldr r6, [%[b], #72]\n\t"
+ "ldr r8, [%[b], #76]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #72]\n\t"
+ "str r5, [%[r], #76]\n\t"
+ "ldr r4, [%[a], #80]\n\t"
+ "ldr r5, [%[a], #84]\n\t"
+ "ldr r6, [%[b], #80]\n\t"
+ "ldr r8, [%[b], #84]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #80]\n\t"
+ "str r5, [%[r], #84]\n\t"
+ "ldr r4, [%[a], #88]\n\t"
+ "ldr r5, [%[a], #92]\n\t"
+ "ldr r6, [%[b], #88]\n\t"
+ "ldr r8, [%[b], #92]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #88]\n\t"
+ "str r5, [%[r], #92]\n\t"
+ "ldr r4, [%[a], #96]\n\t"
+ "ldr r5, [%[a], #100]\n\t"
+ "ldr r6, [%[b], #96]\n\t"
+ "ldr r8, [%[b], #100]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #96]\n\t"
+ "str r5, [%[r], #100]\n\t"
+ "ldr r4, [%[a], #104]\n\t"
+ "ldr r5, [%[a], #108]\n\t"
+ "ldr r6, [%[b], #104]\n\t"
+ "ldr r8, [%[b], #108]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #104]\n\t"
+ "str r5, [%[r], #108]\n\t"
+ "ldr r4, [%[a], #112]\n\t"
+ "ldr r5, [%[a], #116]\n\t"
+ "ldr r6, [%[b], #112]\n\t"
+ "ldr r8, [%[b], #116]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #112]\n\t"
+ "str r5, [%[r], #116]\n\t"
+ "ldr r4, [%[a], #120]\n\t"
+ "ldr r5, [%[a], #124]\n\t"
+ "ldr r6, [%[b], #120]\n\t"
+ "ldr r8, [%[b], #124]\n\t"
+ "sbcs r4, r4, r6\n\t"
+ "sbcs r5, r5, r8\n\t"
+ "str r4, [%[r], #120]\n\t"
+ "str r5, [%[r], #124]\n\t"
+ "sbc %[c], %[c], %[c]\n\t"
+ : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
+ :
+ : "memory", "r4", "r5", "r6", "r8"
+ );
+
+ return c;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Compare two numbers to determine if they are equal.
+ * Constant time implementation.
+ *
+ * a First number to compare.
+ * b Second number to compare.
+ * returns 1 when equal and 0 otherwise.
+ */
+static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b)
+{
+ return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
+ (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) |
+ (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
+ (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) |
+ (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) |
+ (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
+ (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) |
+ (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0;
+}
+
+/* Add two Montgomery form projective points.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+
+#ifdef WOLFSSL_SP_NONBLOCK
+typedef struct sp_1024_proj_point_add_32_ctx {
+ int state;
+ sp_1024_proj_point_dbl_32_ctx dbl_ctx;
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1;
+ sp_digit* t2;
+ sp_digit* t3;
+ sp_digit* t4;
+ sp_digit* t5;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+} sp_1024_proj_point_add_32_ctx;
+
+static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ int err = FP_WOULDBLOCK;
+ sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
+ (void)sizeof(ctx_size_test);
+
+ switch (ctx->state) {
+ case 0: /* INIT */
+ ctx->t1 = t;
+ ctx->t2 = t + 2*32;
+ ctx->t3 = t + 4*32;
+ ctx->t4 = t + 6*32;
+ ctx->t5 = t + 8*32;
+
+ ctx->state = 1;
+ break;
+ case 1:
+ /* Check double */
+ (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y);
+ sp_1024_norm_32(ctx->t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0)
+ {
+ XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
+ ctx->state = 2;
+ }
+ else {
+ ctx->state = 3;
+ }
+ break;
+ case 2:
+ err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
+ if (err == MP_OKAY)
+ ctx->state = 27; /* done */
+ break;
+ case 3:
+ {
+ int i;
+ ctx->rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024));
+ ctx->x = ctx->rp[p->infinity | q->infinity]->x;
+ ctx->y = ctx->rp[p->infinity | q->infinity]->y;
+ ctx->z = ctx->rp[p->infinity | q->infinity]->z;
+
+ ctx->ap[0] = p;
+ ctx->ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ctx->ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ctx->ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ctx->ap[p->infinity]->z[i];
+ }
+ r->infinity = ctx->ap[p->infinity]->infinity;
+
+ ctx->state = 4;
+ break;
+ }
+ case 4:
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 5;
+ break;
+ case 5:
+ sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 6;
+ break;
+ case 6:
+ sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 7;
+ break;
+ case 7:
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 8;
+ break;
+ case 8:
+ sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 9;
+ break;
+ case 9:
+ sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
+ ctx->state = 10;
+ break;
+ case 10:
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 11;
+ break;
+ case 11:
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
+ ctx->state = 12;
+ break;
+ case 12:
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
+ ctx->state = 13;
+ break;
+ case 13:
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
+ ctx->state = 14;
+ break;
+ case 14:
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
+ ctx->state = 15;
+ break;
+ case 15:
+ sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 16;
+ break;
+ case 16:
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 17;
+ break;
+ case 17:
+ sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 18;
+ break;
+ case 18:
+ sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
+ ctx->state = 19;
+ break;
+ case 19:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
+ ctx->state = 20;
+ break;
+ case 20:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod);
+ ctx->state = 21;
+ break;
+ case 21:
+ sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod);
+ ctx->state = 22;
+ break;
+ case 22:
+ sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod);
+ ctx->state = 23;
+ break;
+ case 23:
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
+ ctx->state = 24;
+ break;
+ case 24:
+ sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
+ ctx->state = 25;
+ break;
+ case 25:
+ sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
+ ctx->state = 26;
+ break;
+ case 26:
+ sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod);
+ ctx->state = 27;
+ /* fall-through */
+ case 27:
+ err = MP_OKAY;
+ break;
+ }
+
+ if (err == MP_OKAY && ctx->state != 27) {
+ err = FP_WOULDBLOCK;
+ }
+ return err;
+}
+#endif /* WOLFSSL_SP_NONBLOCK */
+
+static void sp_1024_proj_point_add_32(sp_point_1024* r,
+ const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Ensure only the first point is the same as the result. */
+ if (q == r) {
+ const sp_point_1024* a = p;
+ p = q;
+ q = a;
+ }
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U1 = X1*Z2^2 */
+ sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod);
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S1 = Y1*Z2^3 */
+ sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - U1 */
+ sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
+ /* R = S2 - S1 */
+ sp_1024_mont_sub_32(t4, t4, t3, p1024_mod);
+ /* Z3 = H*Z1*Z2 */
+ sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*U1*H^2 */
+ sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, x, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, y, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
+ sp_1024_mont_sub_32(y, y, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, y, t5, p1024_mod);
+ }
+}
+
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Fast implementation that generates a pre-computation table.
+ * 4 bits of window (no sliding!).
+ * Uses add and double for calculating table.
+ * 1024 doubles.
+ * 268 adds.
+ *
+ * r Resulting point.
+ * g Point to multiply.
+ * k Scalar to multiply by.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
+ int map, int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td[16];
+ sp_point_1024 rtd;
+ sp_digit tmpd[2 * 32 * 5];
+#endif
+ sp_point_1024* t;
+ sp_point_1024* rt;
+ sp_digit* tmp;
+ sp_digit n;
+ int i;
+ int c;
+ int y;
+ int err;
+
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+#ifndef WC_NO_CACHE_RESISTANT
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 17, heap, DYNAMIC_TYPE_ECC);
+#else
+ t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 16, heap, DYNAMIC_TYPE_ECC);
+#endif
+ if (t == NULL)
+ err = MEMORY_E;
+ tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (tmp == NULL)
+ err = MEMORY_E;
+#else
+ t = td;
+ tmp = tmpd;
+#endif
+
+ if (err == MP_OKAY) {
+ /* t[0] = {0, 0, 1} * norm */
+ XMEMSET(&t[0], 0, sizeof(t[0]));
+ t[0].infinity = 1;
+ /* t[1] = {g->x, g->y, g->z} * norm */
+ (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod);
+ (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod);
+ t[1].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp);
+ t[ 2].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp);
+ t[ 3].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp);
+ t[ 4].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp);
+ t[ 5].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp);
+ t[ 6].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp);
+ t[ 7].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp);
+ t[ 8].infinity = 0;
+ sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp);
+ t[ 9].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp);
+ t[10].infinity = 0;
+ sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp);
+ t[11].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp);
+ t[12].infinity = 0;
+ sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp);
+ t[13].infinity = 0;
+ sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp);
+ t[14].infinity = 0;
+ sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp);
+ t[15].infinity = 0;
+
+ i = 30;
+ n = k[i+1] << 0;
+ c = 28;
+ y = (int)(n >> 28);
+ XMEMCPY(rt, &t[y], sizeof(sp_point_1024));
+ n <<= 4;
+ for (; i>=0 || c>=4; ) {
+ if (c < 4) {
+ n |= k[i--];
+ c += 32;
+ }
+ y = (n >> 28) & 0xf;
+ n <<= 4;
+ c -= 4;
+
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_dbl_32(rt, rt, tmp);
+ sp_1024_proj_point_add_32(rt, rt, &t[y], tmp);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, tmp);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (tmp != NULL) {
+ XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 32 * 5);
+ XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
+ }
+ if (t != NULL) {
+ XMEMSET(t, 0, sizeof(sp_point_1024) * 16);
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#else
+ ForceZero(tmpd, sizeof(tmpd));
+ ForceZero(td, sizeof(td));
+#endif
+ sp_1024_point_free_32(rt, 1, heap);
+
+ return err;
+}
+
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Double the Montgomery form projective point p a number of times.
+ *
+ * r Result of repeated doubling of point.
+ * p Point to double.
+ * n Number of times to double
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n,
+ sp_digit* t)
+{
+ sp_digit* w = t;
+ sp_digit* a = t + 2*32;
+ sp_digit* b = t + 4*32;
+ sp_digit* t1 = t + 6*32;
+ sp_digit* t2 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+
+ x = p->x;
+ y = p->y;
+ z = p->z;
+
+ /* Y = 2*Y */
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ /* W = Z^4 */
+ sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod);
+
+#ifndef WOLFSSL_SP_SMALL
+ while (--n > 0)
+#else
+ while (--n >= 0)
+#endif
+ {
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+#ifdef WOLFSSL_SP_SMALL
+ if (n != 0)
+#endif
+ {
+ /* W = W*Y^4 */
+ sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod);
+ }
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+ }
+#ifndef WOLFSSL_SP_SMALL
+ /* A = 3*(X^2 - W) */
+ sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
+ sp_1024_mont_tpl_32(a, t1, p1024_mod);
+ /* B = X*Y^2 */
+ sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
+ /* X = A^2 - 2B */
+ sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(t2, b, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t2, p1024_mod);
+ /* Z = Z*Y */
+ sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
+ /* t2 = Y^4 */
+ sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
+ /* y = 2*A*(B - X) - Y^4 */
+ sp_1024_mont_sub_32(y, b, x, p1024_mod);
+ sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_dbl_32(y, y, p1024_mod);
+ sp_1024_mont_sub_32(y, y, t1, p1024_mod);
+#endif
+ /* Y = Y/2 */
+ sp_1024_div2_32(y, y, p1024_mod);
+}
+
+/* Convert the projective point to affine.
+ * Ordinates are in Montgomery form.
+ *
+ * a Point to convert.
+ * t Temporary data.
+ */
+static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* tmp = t + 4 * 32;
+
+ sp_1024_mont_inv_32(t1, a->z, tmp);
+
+ sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
+
+ sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* A table entry for pre-computed points. */
+typedef struct sp_table_entry_1024 {
+ sp_digit x[32];
+ sp_digit y[32];
+} sp_table_entry_1024;
+
+#ifdef FP_ECC
+#endif /* FP_ECC */
+/* Add two Montgomery form projective points. The second point has a q value of
+ * one.
+ * Only the first point can be the same pointer as the result point.
+ *
+ * r Result of addition.
+ * p First point to add.
+ * q Second point to add.
+ * t Temporary ordinate data.
+ */
+static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p,
+ const sp_point_1024* q, sp_digit* t)
+{
+ const sp_point_1024* ap[2];
+ sp_point_1024* rp[2];
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2*32;
+ sp_digit* t3 = t + 4*32;
+ sp_digit* t4 = t + 6*32;
+ sp_digit* t5 = t + 8*32;
+ sp_digit* x;
+ sp_digit* y;
+ sp_digit* z;
+ int i;
+
+ /* Check double */
+ (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod);
+ sp_1024_norm_32(t1);
+ if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) &
+ (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) {
+ sp_1024_proj_point_dbl_32(r, p, t);
+ }
+ else {
+ rp[0] = r;
+
+ /*lint allow cast to different type of pointer*/
+ rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/
+ XMEMSET(rp[1], 0, sizeof(sp_point_1024));
+ x = rp[p->infinity | q->infinity]->x;
+ y = rp[p->infinity | q->infinity]->y;
+ z = rp[p->infinity | q->infinity]->z;
+
+ ap[0] = p;
+ ap[1] = q;
+ for (i=0; i<32; i++) {
+ r->x[i] = ap[p->infinity]->x[i];
+ }
+ for (i=0; i<32; i++) {
+ r->y[i] = ap[p->infinity]->y[i];
+ }
+ for (i=0; i<32; i++) {
+ r->z[i] = ap[p->infinity]->z[i];
+ }
+ r->infinity = ap[p->infinity]->infinity;
+
+ /* U2 = X2*Z1^2 */
+ sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
+ /* S2 = Y2*Z1^3 */
+ sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
+ /* H = U2 - X1 */
+ sp_1024_mont_sub_32(t2, t2, x, p1024_mod);
+ /* R = S2 - Y1 */
+ sp_1024_mont_sub_32(t4, t4, y, p1024_mod);
+ /* Z3 = H*Z1 */
+ sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod);
+ /* X3 = R^2 - H^3 - 2*X1*H^2 */
+ sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(x, t1, t5, p1024_mod);
+ sp_1024_mont_dbl_32(t1, t3, p1024_mod);
+ sp_1024_mont_sub_32(x, x, t1, p1024_mod);
+ /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
+ sp_1024_mont_sub_32(t3, t3, x, p1024_mod);
+ sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_sub_32(y, t3, t5, p1024_mod);
+ }
+}
+
+#ifdef WOLFSSL_SP_SMALL
+#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
+/* Generate the pre-computed table of points for the base point.
+ *
+ * width = 4
+ * 16 entries
+ * 256 bits between
+ *
+ * a The base point.
+ * table Place to store generated point data.
+ * tmp Temporary data.
+ * heap Heap to use for allocation.
+ */
+static int sp_1024_gen_stripe_table_32(const sp_point_1024* a,
+ sp_table_entry_1024* table, sp_digit* tmp, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 td;
+ sp_point_1024 s1d;
+ sp_point_1024 s2d;
+#endif
+ sp_point_1024* t;
+ sp_point_1024* s1 = NULL;
+ sp_point_1024* s2 = NULL;
+ int i;
+ int j;
+ int err;
+
+ (void)heap;
+
+ err = sp_1024_point_new_32(heap, td, t);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s1d, s1);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, s2d, s2);
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ t->infinity = 0;
+ sp_1024_proj_to_affine_32(t, tmp);
+
+ XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s1->infinity = 0;
+ XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ s2->infinity = 0;
+
+ /* table[0] = {0, 0, infinity} */
+ XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
+ /* table[1] = Affine version of 'a' in Montgomery form */
+ XMEMCPY(table[1].x, t->x, sizeof(table->x));
+ XMEMCPY(table[1].y, t->y, sizeof(table->y));
+
+ for (i=1; i<4; i++) {
+ sp_1024_proj_point_dbl_n_32(t, 256, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[1<x, sizeof(table->x));
+ XMEMCPY(table[1<y, sizeof(table->y));
+ }
+
+ for (i=1; i<4; i++) {
+ XMEMCPY(s1->x, table[1<x));
+ XMEMCPY(s1->y, table[1<y));
+ for (j=(1<x, table[j-(1<x));
+ XMEMCPY(s2->y, table[j-(1<y));
+ sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp);
+ sp_1024_proj_to_affine_32(t, tmp);
+ XMEMCPY(table[j].x, t->x, sizeof(table->x));
+ XMEMCPY(table[j].y, t->y, sizeof(table->y));
+ }
+ }
+ }
+
+ sp_1024_point_free_32(s2, 0, heap);
+ sp_1024_point_free_32(s1, 0, heap);
+ sp_1024_point_free_32( t, 0, heap);
+
+ return err;
+}
+
+#endif /* FP_ECC || !WOLFSSL_SP_SMALL */
+/* Multiply the point by the scalar and return the result.
+ * If map is true then convert result to affine coordinates.
+ *
+ * Stripe implementation.
+ * Pre-generated: 2^0, 2^256, ...
+ * Pre-generated: products of all combinations of above.
+ * 4 doubles and adds (with qz=1)
+ *
+ * r Resulting point.
+ * k Scalar to multiply by.
+ * table Pre-computed table.
+ * map Indicates whether to convert result to affine.
+ * ct Constant time required.
+ * heap Heap to use for allocation.
+ * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
+ */
+static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g,
+ const sp_table_entry_1024* table, const sp_digit* k, int map,
+ int ct, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 rtd;
+ sp_point_1024 pd;
+ sp_digit td[2 * 32 * 5];
+#endif
+ sp_point_1024* rt;
+ sp_point_1024* p = NULL;
+ sp_digit* t;
+ int i;
+ int j;
+ int y;
+ int x;
+ int err;
+
+ (void)g;
+ /* Constant time used for cache attack resistance implementation. */
+ (void)ct;
+ (void)heap;
+
+
+ err = sp_1024_point_new_32(heap, rtd, rt);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap,
+ DYNAMIC_TYPE_ECC);
+ if (t == NULL) {
+ err = MEMORY_E;
+ }
+#else
+ t = td;
+#endif
+
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+
+ y = 0;
+ x = 255;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+ XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
+ rt->infinity = !y;
+ for (i=254; i>=0; i--) {
+ y = 0;
+ x = i;
+ for (j=0; j<4; j++) {
+ y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
+ x += 256;
+ }
+
+ sp_1024_proj_point_dbl_32(rt, rt, t);
+ XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
+ XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
+ p->infinity = !y;
+ sp_1024_proj_point_add_qz1_32(rt, rt, p, t);
+ }
+
+ if (map != 0) {
+ sp_1024_map_32(r, rt, t);
+ }
+ else {
+ XMEMCPY(r, rt, sizeof(sp_point_1024));
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (t != NULL) {
+ XFREE(t, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(rt, 0, heap);
+
+ return err;
+}
+
+#ifdef FP_ECC
+#ifndef FP_ENTRIES
+ #define FP_ENTRIES 16
+#endif
+
+/* Cache entry - holds precomputation tables for a point. */
+typedef struct sp_cache_1024_t {
+ /* X ordinate of point that table was generated from. */
+ sp_digit x[32];
+ /* Y ordinate of point that table was generated from. */
+ sp_digit y[32];
+ /* Precomputation table for point. */
+ sp_table_entry_1024 table[16];
+ /* Count of entries in table. */
+ uint32_t cnt;
+ /* Point and table set in entry. */
+ int set;
+} sp_cache_1024_t;
+
+/* Cache of tables. */
+static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
+/* Index of last entry in cache. */
+static THREAD_LS_T int sp_cache_1024_last = -1;
+/* Cache has been initialized. */
+static THREAD_LS_T int sp_cache_1024_inited = 0;
+
+#ifndef HAVE_THREAD_LS
+ static volatile int initCacheMutex_1024 = 0;
+ static wolfSSL_Mutex sp_cache_1024_lock;
+#endif
+
+/* Get the cache entry for the point.
+ *
+ * g [in] Point scalar multipling.
+ * cache [out] Cache table to use.
+ */
+static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
+{
+ int i;
+ int j;
+ uint32_t least;
+
+ if (sp_cache_1024_inited == 0) {
+ for (i=0; i .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit qx_px[2 * 32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ qx_px = td + 8 * 32 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+
+ sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* h = t + 8 * 32;
+ sp_digit* r = t + 10 * 32;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_32(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_32(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_32(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_32(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_32(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_32(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 32;
+ sp_digit* pz2 = t + 2 * 32;
+ sp_digit* rx = t + 4 * 32;
+ sp_digit* ry = t + 6 * 32;
+ sp_digit* l = t + 8 * 32;
+ sp_digit* ty = t + 10 * 32;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_32(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_32(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_32(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_32(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* t2 = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_32(l, py, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_32(t2, t1, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_32(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 32;
+ sp_digit* c = t + 2 * 2 * 32;
+ sp_digit* l = t + 4 * 2 * 32;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_32(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_32(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_32(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_32(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 32);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 32);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 32;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_32(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_32(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_32(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 32 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_32(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_32(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_32(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_32(c, c, neg, t);
+ sp_1024_mont_map_32(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_32(c, c, t);
+ sp_1024_mont_map_32(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(neg, 1, NULL);
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[64];
+ sp_digit (*pre_vy)[64];
+ sp_digit (*pre_nvy)[64];
+#else
+ sp_digit t[6 * 2 * 32];
+ sp_digit vx[2 * 32];
+ sp_digit vy[2 * 32];
+ sp_digit pre_vx[16][64];
+ sp_digit pre_vy[16][64];
+ sp_digit pre_nvy[16][64];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 32 * 2;
+ vy = td + 7 * 32 * 2;
+ pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2);
+ pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2);
+ pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_32(p, pm);
+ sp_1024_point_from_ecc_point_32(q, qm);
+
+ err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
+ sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
+ sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_32(vx, vy, t);
+ sp_1024_proj_sqr_32(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_32(vx, vx, t);
+ sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
+ sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_32(c, 1, NULL);
+ sp_1024_point_free_32(q, 1, NULL);
+ sp_1024_point_free_32(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_32(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
+ a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
+ a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+ int i;
+ int j = 0;
+ word32 s = 0;
+
+ r[0] = 0;
+ for (i = n-1; i >= 0; i--) {
+ r[j] |= (((sp_digit)a[i]) << s);
+ if (s >= 24U) {
+ r[j] &= 0xffffffff;
+ s = 32U - s;
+ if (j + 1 >= size) {
+ break;
+ }
+ r[++j] = (sp_digit)a[i] >> s;
+ s = 8U - s;
+ }
+ else {
+ s += 8U;
+ }
+ }
+
+ for (j++; j < size; j++) {
+ r[j] = 0;
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_32(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*32];
+ sp_digit t2d[2*32];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int32_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 32;
+ t2 = d + 2 * 32;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_32(t1, point->y);
+ (void)sp_1024_mod_32(t1, t1, p1024_mod);
+ sp_1024_sqr_32(t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ sp_1024_mul_32(t2, t2, point->x);
+ (void)sp_1024_mod_32(t2, t2, p1024_mod);
+ (void)sp_1024_sub_32(t2, p1024_mod, t2);
+ sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_32(t1, p1024_mod);
+ sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_32(t1);
+ if (!sp_1024_iszero_32(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_32(pub, NULL);
+ }
+
+ sp_1024_point_free_32(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[32];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_32(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_32(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 32, pX);
+ sp_1024_from_mp(pub->y, 32, pY);
+ sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 32, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_32(pub->x) != 0) &&
+ (sp_1024_iszero_32(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_32(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+ err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) ||
+ (sp_1024_iszero_32(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+ err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_32(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_32(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_32(p, 0, heap);
+ sp_1024_point_free_32(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_SP_ARM_CORTEX_M_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c
index 77a59b3ae..48d87b513 100644
--- a/wolfcrypt/src/sp_int.c
+++ b/wolfcrypt/src/sp_int.c
@@ -2364,7 +2364,7 @@ void sp_forcezero(sp_int* a)
*
* @return MP_OKAY on success.
*/
-int sp_copy(sp_int* a, sp_int* r)
+int sp_copy(const sp_int* a, sp_int* r)
{
int err = MP_OKAY;
@@ -2686,7 +2686,7 @@ int sp_is_bit_set(sp_int* a, unsigned int b)
*
* @return The number of bits in the number.
*/
-int sp_count_bits(sp_int* a)
+int sp_count_bits(const sp_int* a)
{
int r = 0;
@@ -2997,7 +2997,8 @@ int sp_cmp_d(sp_int* a, sp_int_digit d)
#if defined(WOLFSSL_SP_INT_NEGATIVE) || !defined(NO_PWDBASED) || \
defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || \
- (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
+ ((defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA)) && \
+ !defined(WOLFSSL_RSA_VERIFY_ONLY))
/* Add a one digit number to the multi-precision number.
*
* @param [in] a SP integer be added to.
@@ -3487,7 +3488,7 @@ static void _sp_div_small(sp_int* a, sp_int_digit d, sp_int* r,
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
-/* Divide a multi-precision number by a digit size number and calcualte
+/* Divide a multi-precision number by a digit size number and calculate
* remainder.
* r = a / d; rem = a % d
*
@@ -3958,7 +3959,8 @@ int sp_sub(sp_int* a, sp_int* b, sp_int* r)
****************************/
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
- (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES))
+ (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \
+ defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE)
/* Add two value and reduce: r = (a + b) % m
*
* @param [in] a SP integer to add.
@@ -4002,7 +4004,8 @@ int sp_addmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r)
FREE_SP_INT(t, NULL);
return err;
}
-#endif /* WOLFSSL_SP_MATH_ALL || (!WOLFSSL_SP_MATH && WOLFSSL_CUSTOM_CURVES) */
+#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_CUSTOM_CURVES) ||
+ * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */
#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
/* Sub b from a and reduce: r = (a - b) % m
@@ -4696,7 +4699,7 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r)
err = sp_div(a, m, NULL, r);
}
#else
- ALLOC_SP_INT(t, m->used, err, NULL);
+ ALLOC_SP_INT(t, a->used + 1, err, NULL);
if (err == MP_OKAY) {
sp_init_size(t, a->used + 1);
err = sp_div(a, m, NULL, t);
@@ -7679,7 +7682,8 @@ int sp_mul(sp_int* a, sp_int* b, sp_int* r)
}
/* END SP_MUL implementations. */
-#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH)
+#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
+ defined(WOLFCRYPT_HAVE_ECCSI)
/* Multiply a by b mod m and store in r: r = (a * b) mod m
*
* @param [in] a SP integer to multiply.
@@ -11667,7 +11671,8 @@ int sp_sqrmod(sp_int* a, sp_int* m, sp_int* r)
* Montogmery functions
**********************/
-#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH)
+#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
+ defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE)
/* Reduce a number in montgomery form.
*
* Assumes a and m are not NULL and m is not 0.
@@ -12063,7 +12068,8 @@ int sp_mont_norm(sp_int* norm, sp_int* m)
return err;
}
-#endif
+#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH ||
+ * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */
/*********************************
* To and from binary and strings.
@@ -12078,7 +12084,7 @@ int sp_mont_norm(sp_int* norm, sp_int* m)
*
* @return The count of 8-bit values.
*/
-int sp_unsigned_bin_size(sp_int* a)
+int sp_unsigned_bin_size(const sp_int* a)
{
int cnt = 0;
diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c
index fd8a9897e..060114fb5 100644
--- a/wolfcrypt/src/sp_x86_64.c
+++ b/wolfcrypt/src/sp_x86_64.c
@@ -1,6 +1,6 @@
/* sp.c
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -60,12 +60,15 @@ extern void sp_2048_from_bin_movbe(sp_digit* r, int size, const byte* a, int n);
*/
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_2048_from_bin_movbe(r, size, a, n);
}
- else {
+ else
+#endif
+ {
sp_2048_from_bin_bswap(r, size, a, n);
}
}
@@ -87,7 +90,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -121,7 +125,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -162,12 +168,15 @@ extern void sp_2048_to_bin_movbe(sp_digit* r, byte* a);
*/
static void sp_2048_to_bin(sp_digit* r, byte* a)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_2048_to_bin_movbe(r, a);
}
- else {
+ else
+#endif
+ {
sp_2048_to_bin_bswap(r, a);
}
}
@@ -184,16 +193,13 @@ extern void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b);
extern sp_digit sp_2048_dbl_16(sp_digit* r, const sp_digit* a);
extern void sp_2048_sqr_32(sp_digit* r, const sp_digit* a);
-#ifdef HAVE_INTEL_AVX2
extern void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b);
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
extern void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a);
-#endif /* HAVE_INTEL_AVX2 */
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b);
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -202,7 +208,8 @@ extern void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a);
*/
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -212,12 +219,11 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
extern void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b);
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
-extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b);
/* r = 2^n mod m where n is the number of bits to reduce by.
* Given m must be 2048 bits, just need to subtract.
*
@@ -243,8 +249,8 @@ extern void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, sp_digit mp);
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_16(r, a, b);
sp_2048_mont_reduce_16(r, m, mp);
@@ -257,8 +263,8 @@ static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_16(r, a);
sp_2048_mont_reduce_16(r, m, mp);
@@ -267,6 +273,27 @@ static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit*
extern sp_digit sp_2048_cond_sub_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, sp_digit b);
extern void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit b);
+#ifdef _WIN64
+#if _MSC_VER < 1920
+extern sp_digit div_2048_word_asm_16(sp_digit d1, sp_digit d0, sp_digit div);
+#endif /* _MSC_VER < 1920 */
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+static WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+#if _MSC_VER >= 1920
+ return _udiv128(d1, d0, div, NULL);
+#else
+ return div_2048_word_asm_16(d1, d0, div);
+#endif
+}
+#else
/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
* d1 The high order half of the number to divide.
@@ -286,6 +313,7 @@ static WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0,
);
return r;
}
+#endif /* _WIN64 */
/* AND m into each word of a and store in r.
*
* r A single precision integer.
@@ -329,8 +357,10 @@ extern int64_t sp_2048_cmp_16(const sp_digit* a, const sp_digit* b);
static WC_INLINE int sp_2048_div_16(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[32], t2[17];
- sp_digit div, r1;
+ sp_digit t1[32];
+ sp_digit t2[17];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -383,7 +413,8 @@ static WC_INLINE int sp_2048_div_16(const sp_digit* a, const sp_digit* d, sp_dig
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_2048_div_16(a, m, NULL, r);
}
@@ -406,13 +437,14 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(33 * 32) + 32];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -499,34 +531,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -572,8 +604,8 @@ extern void sp_2048_mont_reduce_avx2_16(sp_digit* a, const sp_digit* m, sp_digit
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_avx2_16(r, a, b);
sp_2048_mont_reduce_avx2_16(r, m, mp);
@@ -588,8 +620,8 @@ static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_di
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_avx2_16(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_avx2_16(r, a);
sp_2048_mont_reduce_avx2_16(r, m, mp);
@@ -615,13 +647,14 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi
sp_digit td[(33 * 32) + 32];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -708,34 +741,34 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -771,7 +804,7 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi
}
#endif /* HAVE_INTEL_AVX2 */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -788,7 +821,7 @@ static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m)
sp_2048_sub_in_place_32(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
extern sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp);
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -800,8 +833,8 @@ extern void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp);
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_32(r, a, b);
sp_2048_mont_reduce_32(r, m, mp);
@@ -814,8 +847,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_32(r, a);
sp_2048_mont_reduce_32(r, m, mp);
@@ -824,6 +857,27 @@ static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit*
#if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
extern sp_digit sp_2048_cond_sub_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit b);
+#ifdef _WIN64
+#if _MSC_VER < 1920
+extern sp_digit div_2048_word_asm_32(sp_digit d1, sp_digit d0, sp_digit div);
+#endif /* _MSC_VER < 1920 */
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+static WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+#if _MSC_VER >= 1920
+ return _udiv128(d1, d0, div, NULL);
+#else
+ return div_2048_word_asm_32(d1, d0, div);
+#endif
+}
+#else
/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
* d1 The high order half of the number to divide.
@@ -843,6 +897,7 @@ static WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0,
);
return r;
}
+#endif /* _WIN64 */
/* AND m into each word of a and store in r.
*
* r A single precision integer.
@@ -886,8 +941,10 @@ extern int64_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b);
static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[64], t2[33];
- sp_digit div, r1;
+ sp_digit t1[64];
+ sp_digit t2[33];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -940,7 +997,8 @@ static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_dig
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_2048_div_32(a, m, NULL, r);
}
@@ -959,8 +1017,10 @@ extern sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b
static WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[64], t2[33];
- sp_digit div, r1;
+ sp_digit t1[64];
+ sp_digit t2[33];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -1017,7 +1077,8 @@ static WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const sp_digit* d, s
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_2048_div_32_cond(a, m, NULL, r);
}
@@ -1041,13 +1102,14 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(33 * 64) + 64];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -1134,34 +1196,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -1208,8 +1270,8 @@ extern void sp_2048_mont_reduce_avx2_32(sp_digit* a, const sp_digit* m, sp_digit
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_2048_mul_avx2_32(r, a, b);
sp_2048_mont_reduce_avx2_32(r, m, mp);
@@ -1224,8 +1286,8 @@ static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_di
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_2048_mont_sqr_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_2048_mont_sqr_avx2_32(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_2048_sqr_avx2_32(r, a);
sp_2048_mont_reduce_avx2_32(r, m, mp);
@@ -1252,13 +1314,14 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi
sp_digit td[(33 * 64) + 64];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -1345,34 +1408,34 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -1422,11 +1485,13 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[64], md[32], rd[64];
+ sp_digit ad[64];
+ sp_digit md[32];
+ sp_digit rd[64];
#else
sp_digit* d = NULL;
#endif
@@ -1595,12 +1660,14 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit a[64], d[32], m[32];
+ sp_digit a[64];
+ sp_digit d[32];
+ sp_digit m[32];
#else
sp_digit* d = NULL;
sp_digit* a;
@@ -1693,14 +1760,17 @@ extern sp_digit sp_2048_cond_add_avx2_16(sp_digit* r, const sp_digit* a, const s
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit ad[32 * 2];
- sp_digit pd[16], qd[16], dpd[16];
- sp_digit tmpad[32], tmpbd[32];
+ sp_digit pd[16];
+ sp_digit qd[16];
+ sp_digit dpd[16];
+ sp_digit tmpad[32];
+ sp_digit tmpbd[32];
#else
sp_digit* t = NULL;
#endif
@@ -1840,7 +1910,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
return err;
}
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
#endif /* WOLFSSL_HAVE_SP_RSA */
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
@@ -1860,17 +1930,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = 32;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 32; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -1883,14 +1955,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 32; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -1917,10 +1991,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -1980,10 +2057,12 @@ static int sp_2048_mod_exp_2_avx2_32(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2022,34 +2101,34 @@ static int sp_2048_mod_exp_2_avx2_32(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_2048_lshift_32(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -2103,10 +2182,12 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2145,34 +2226,34 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_2048_lshift_32(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -2220,11 +2301,13 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
+ sp_digit b[64];
+ sp_digit e[32];
+ sp_digit m[32];
sp_digit* r = b;
word32 i;
#ifdef HAVE_INTEL_AVX2
@@ -2269,6 +2352,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
sp_2048_to_bin(r, out);
*outLen = 256;
for (i=0; i<256 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -2288,10 +2372,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[32], e[16], m[16];
+ sp_digit b[32];
+ sp_digit e[16];
+ sp_digit m[16];
sp_digit* r = b;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -2329,7 +2416,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_2048 */
@@ -2345,12 +2432,15 @@ extern void sp_3072_from_bin_movbe(sp_digit* r, int size, const byte* a, int n);
*/
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_3072_from_bin_movbe(r, size, a, n);
}
- else {
+ else
+#endif
+ {
sp_3072_from_bin_bswap(r, size, a, n);
}
}
@@ -2372,7 +2462,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -2406,7 +2497,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -2447,12 +2540,15 @@ extern void sp_3072_to_bin_movbe(sp_digit* r, byte* a);
*/
static void sp_3072_to_bin(sp_digit* r, byte* a)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_3072_to_bin_movbe(r, a);
}
- else {
+ else
+#endif
+ {
sp_3072_to_bin_bswap(r, a);
}
}
@@ -2469,13 +2565,9 @@ extern void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b);
extern sp_digit sp_3072_dbl_12(sp_digit* r, const sp_digit* a);
extern void sp_3072_sqr_24(sp_digit* r, const sp_digit* a);
-#ifdef HAVE_INTEL_AVX2
extern void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b);
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
extern void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a);
-#endif /* HAVE_INTEL_AVX2 */
extern sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b);
extern sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b);
@@ -2484,16 +2576,12 @@ extern void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b);
extern sp_digit sp_3072_dbl_24(sp_digit* r, const sp_digit* a);
extern void sp_3072_sqr_48(sp_digit* r, const sp_digit* a);
-#ifdef HAVE_INTEL_AVX2
extern void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b);
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
extern void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a);
-#endif /* HAVE_INTEL_AVX2 */
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -2502,7 +2590,8 @@ extern void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a);
*/
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -2512,7 +2601,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
extern void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b);
@@ -2542,8 +2631,8 @@ extern void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, sp_digit mp);
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_24(r, a, b);
sp_3072_mont_reduce_24(r, m, mp);
@@ -2556,8 +2645,8 @@ static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_24(r, a);
sp_3072_mont_reduce_24(r, m, mp);
@@ -2566,6 +2655,27 @@ static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit*
extern sp_digit sp_3072_cond_sub_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, sp_digit b);
extern void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit b);
+#ifdef _WIN64
+#if _MSC_VER < 1920
+extern sp_digit div_3072_word_asm_24(sp_digit d1, sp_digit d0, sp_digit div);
+#endif /* _MSC_VER < 1920 */
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+static WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+#if _MSC_VER >= 1920
+ return _udiv128(d1, d0, div, NULL);
+#else
+ return div_3072_word_asm_24(d1, d0, div);
+#endif
+}
+#else
/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
* d1 The high order half of the number to divide.
@@ -2585,6 +2695,7 @@ static WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0,
);
return r;
}
+#endif /* _WIN64 */
/* AND m into each word of a and store in r.
*
* r A single precision integer.
@@ -2628,8 +2739,10 @@ extern int64_t sp_3072_cmp_24(const sp_digit* a, const sp_digit* b);
static WC_INLINE int sp_3072_div_24(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[48], t2[25];
- sp_digit div, r1;
+ sp_digit t1[48];
+ sp_digit t2[25];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -2682,7 +2795,8 @@ static WC_INLINE int sp_3072_div_24(const sp_digit* a, const sp_digit* d, sp_dig
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_3072_div_24(a, m, NULL, r);
}
@@ -2705,13 +2819,14 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(33 * 48) + 48];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -2798,34 +2913,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -2871,8 +2986,8 @@ extern void sp_3072_mont_reduce_avx2_24(sp_digit* a, const sp_digit* m, sp_digit
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_avx2_24(r, a, b);
sp_3072_mont_reduce_avx2_24(r, m, mp);
@@ -2887,8 +3002,8 @@ static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_di
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_avx2_24(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_avx2_24(r, a);
sp_3072_mont_reduce_avx2_24(r, m, mp);
@@ -2914,13 +3029,14 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi
sp_digit td[(33 * 48) + 48];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3007,34 +3123,34 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -3070,7 +3186,7 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi
}
#endif /* HAVE_INTEL_AVX2 */
-#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
+#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
/* r = 2^n mod m where n is the number of bits to reduce by.
@@ -3087,7 +3203,7 @@ static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m)
sp_3072_sub_in_place_48(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
extern sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp);
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -3099,8 +3215,8 @@ extern void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp);
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_48(r, a, b);
sp_3072_mont_reduce_48(r, m, mp);
@@ -3113,8 +3229,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_48(r, a);
sp_3072_mont_reduce_48(r, m, mp);
@@ -3123,6 +3239,27 @@ static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit*
#if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
extern sp_digit sp_3072_cond_sub_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit b);
+#ifdef _WIN64
+#if _MSC_VER < 1920
+extern sp_digit div_3072_word_asm_48(sp_digit d1, sp_digit d0, sp_digit div);
+#endif /* _MSC_VER < 1920 */
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+static WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+#if _MSC_VER >= 1920
+ return _udiv128(d1, d0, div, NULL);
+#else
+ return div_3072_word_asm_48(d1, d0, div);
+#endif
+}
+#else
/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
* d1 The high order half of the number to divide.
@@ -3142,6 +3279,7 @@ static WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0,
);
return r;
}
+#endif /* _WIN64 */
/* AND m into each word of a and store in r.
*
* r A single precision integer.
@@ -3185,8 +3323,10 @@ extern int64_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b);
static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[96], t2[49];
- sp_digit div, r1;
+ sp_digit t1[96];
+ sp_digit t2[49];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -3239,7 +3379,8 @@ static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_dig
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_3072_div_48(a, m, NULL, r);
}
@@ -3258,8 +3399,10 @@ extern sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b
static WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[96], t2[49];
- sp_digit div, r1;
+ sp_digit t1[96];
+ sp_digit t2[49];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -3316,7 +3459,8 @@ static WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const sp_digit* d, s
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_3072_div_48_cond(a, m, NULL, r);
}
@@ -3340,13 +3484,14 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(33 * 96) + 96];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3433,34 +3578,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -3507,8 +3652,8 @@ extern void sp_3072_mont_reduce_avx2_48(sp_digit* a, const sp_digit* m, sp_digit
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_3072_mul_avx2_48(r, a, b);
sp_3072_mont_reduce_avx2_48(r, m, mp);
@@ -3523,8 +3668,8 @@ static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_di
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_3072_mont_sqr_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_3072_mont_sqr_avx2_48(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_3072_sqr_avx2_48(r, a);
sp_3072_mont_reduce_avx2_48(r, m, mp);
@@ -3551,13 +3696,14 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi
sp_digit td[(33 * 96) + 96];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -3644,34 +3790,34 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -3721,11 +3867,13 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[96], md[48], rd[96];
+ sp_digit ad[96];
+ sp_digit md[48];
+ sp_digit rd[96];
#else
sp_digit* d = NULL;
#endif
@@ -3894,12 +4042,14 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit a[96], d[48], m[48];
+ sp_digit a[96];
+ sp_digit d[48];
+ sp_digit m[48];
#else
sp_digit* d = NULL;
sp_digit* a;
@@ -3992,14 +4142,17 @@ extern sp_digit sp_3072_cond_add_avx2_24(sp_digit* r, const sp_digit* a, const s
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit ad[48 * 2];
- sp_digit pd[24], qd[24], dpd[24];
- sp_digit tmpad[48], tmpbd[48];
+ sp_digit pd[24];
+ sp_digit qd[24];
+ sp_digit dpd[24];
+ sp_digit tmpad[48];
+ sp_digit tmpbd[48];
#else
sp_digit* t = NULL;
#endif
@@ -4139,7 +4292,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
return err;
}
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
#endif /* WOLFSSL_HAVE_SP_RSA */
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
@@ -4159,17 +4312,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = 48;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 48; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -4182,14 +4337,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 48; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -4216,10 +4373,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -4279,10 +4439,12 @@ static int sp_3072_mod_exp_2_avx2_48(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4321,34 +4483,34 @@ static int sp_3072_mod_exp_2_avx2_48(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_3072_lshift_48(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -4402,10 +4564,12 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -4444,34 +4608,34 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_3072_lshift_48(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -4519,11 +4683,13 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
+ sp_digit b[96];
+ sp_digit e[48];
+ sp_digit m[48];
sp_digit* r = b;
word32 i;
#ifdef HAVE_INTEL_AVX2
@@ -4568,6 +4734,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
sp_3072_to_bin(r, out);
*outLen = 384;
for (i=0; i<384 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -4587,10 +4754,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[48], e[24], m[24];
+ sp_digit b[48];
+ sp_digit e[24];
+ sp_digit m[24];
sp_digit* r = b;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -4628,7 +4798,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
return err;
}
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* !WOLFSSL_SP_NO_3072 */
@@ -4644,12 +4814,15 @@ extern void sp_4096_from_bin_movbe(sp_digit* r, int size, const byte* a, int n);
*/
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_4096_from_bin_movbe(r, size, a, n);
}
- else {
+ else
+#endif
+ {
sp_4096_from_bin_bswap(r, size, a, n);
}
}
@@ -4671,7 +4844,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -4705,7 +4879,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -4746,12 +4922,15 @@ extern void sp_4096_to_bin_movbe(sp_digit* r, byte* a);
*/
static void sp_4096_to_bin(sp_digit* r, byte* a)
{
+#ifndef NO_MOVBE_SUPPORT
word32 cpuid_flags = cpuid_get_flags();
if (IS_INTEL_MOVBE(cpuid_flags)) {
sp_4096_to_bin_movbe(r, a);
}
- else {
+ else
+#endif
+ {
sp_4096_to_bin_bswap(r, a);
}
}
@@ -4763,13 +4942,9 @@ extern void sp_4096_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b);
extern sp_digit sp_2048_dbl_32(sp_digit* r, const sp_digit* a);
extern void sp_4096_sqr_64(sp_digit* r, const sp_digit* a);
-#ifdef HAVE_INTEL_AVX2
extern void sp_4096_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b);
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
extern void sp_4096_sqr_avx2_64(sp_digit* r, const sp_digit* a);
-#endif /* HAVE_INTEL_AVX2 */
/* Caclulate the bottom digit of -1/a mod 2^n.
*
@@ -4778,7 +4953,8 @@ extern void sp_4096_sqr_avx2_64(sp_digit* r, const sp_digit* a);
*/
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
{
- sp_digit x, b;
+ sp_digit x;
+ sp_digit b;
b = a[0];
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
@@ -4788,7 +4964,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
x *= 2 - b * x; /* here x*a==1 mod 2**64 */
/* rho = -1/m mod b */
- *rho = -x;
+ *rho = (sp_digit)0 - x;
}
extern void sp_4096_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b);
@@ -4807,7 +4983,7 @@ static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m)
sp_4096_sub_in_place_64(r, m);
}
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
extern sp_digit sp_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp);
/* Multiply two Montogmery form numbers mod the modulus (prime).
@@ -4819,8 +4995,8 @@ extern void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp);
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_64(r, a, b);
sp_4096_mont_reduce_64(r, m, mp);
@@ -4833,8 +5009,8 @@ static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit*
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_64(r, a);
sp_4096_mont_reduce_64(r, m, mp);
@@ -4843,6 +5019,27 @@ static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit*
#if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
extern sp_digit sp_4096_cond_sub_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
extern void sp_4096_mul_d_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit b);
+#ifdef _WIN64
+#if _MSC_VER < 1920
+extern sp_digit div_4096_word_asm_64(sp_digit d1, sp_digit d0, sp_digit div);
+#endif /* _MSC_VER < 1920 */
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+static WC_INLINE sp_digit div_4096_word_64(sp_digit d1, sp_digit d0,
+ sp_digit div)
+{
+#if _MSC_VER >= 1920
+ return _udiv128(d1, d0, div, NULL);
+#else
+ return div_4096_word_asm_64(d1, d0, div);
+#endif
+}
+#else
/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
* d1 The high order half of the number to divide.
@@ -4862,6 +5059,7 @@ static WC_INLINE sp_digit div_4096_word_64(sp_digit d1, sp_digit d0,
);
return r;
}
+#endif /* _WIN64 */
/* AND m into each word of a and store in r.
*
* r A single precision integer.
@@ -4905,8 +5103,10 @@ extern int64_t sp_4096_cmp_64(const sp_digit* a, const sp_digit* b);
static WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[128], t2[65];
- sp_digit div, r1;
+ sp_digit t1[128];
+ sp_digit t2[65];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -4959,7 +5159,8 @@ static WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_dig
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_4096_div_64(a, m, NULL, r);
}
@@ -4978,8 +5179,10 @@ extern sp_digit sp_4096_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b
static WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
sp_digit* r)
{
- sp_digit t1[128], t2[65];
- sp_digit div, r1;
+ sp_digit t1[128];
+ sp_digit t2[65];
+ sp_digit div;
+ sp_digit r1;
int i;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -5036,7 +5239,8 @@ static WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, s
* m A single precision number that is the modulus to reduce with.
* returns MP_OKAY indicating success.
*/
-static WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
+static WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a,
+ const sp_digit* m)
{
return sp_4096_div_64_cond(a, m, NULL, r);
}
@@ -5060,13 +5264,14 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
sp_digit td[(33 * 128) + 128];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5153,34 +5358,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -5227,8 +5432,8 @@ extern void sp_4096_mont_reduce_avx2_64(sp_digit* a, const sp_digit* m, sp_digit
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
+static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* b, const sp_digit* m, sp_digit mp)
{
sp_4096_mul_avx2_64(r, a, b);
sp_4096_mont_reduce_avx2_64(r, m, mp);
@@ -5243,8 +5448,8 @@ static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_di
* m Modulus (prime).
* mp Montogmery mulitplier.
*/
-static void sp_4096_mont_sqr_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
+static void sp_4096_mont_sqr_avx2_64(sp_digit* r, const sp_digit* a,
+ const sp_digit* m, sp_digit mp)
{
sp_4096_sqr_avx2_64(r, a);
sp_4096_mont_reduce_avx2_64(r, m, mp);
@@ -5271,13 +5476,14 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi
sp_digit td[(33 * 128) + 128];
#endif
sp_digit* t[32];
- sp_digit* rt;
+ sp_digit* rt = NULL;
sp_digit* norm;
sp_digit mp = 1;
sp_digit n;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -5364,34 +5570,34 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
for (; i>=0 || c>=5; ) {
if (c >= 5) {
- y = (int)((n >> 59) & 0x1f);
+ y = (byte)((n >> 59) & 0x1f);
n <<= 5;
c -= 5;
}
else if (c == 0) {
n = e[i--];
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n <<= 5;
c = 59;
}
else {
- y = (int)(n >> 59);
+ y = (byte)(n >> 59);
n = e[i--];
c = 5 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
@@ -5441,11 +5647,13 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
+ const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
- sp_digit ad[128], md[64], rd[128];
+ sp_digit ad[128];
+ sp_digit md[64];
+ sp_digit rd[128];
#else
sp_digit* d = NULL;
#endif
@@ -5614,12 +5822,14 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit a[128], d[64], m[64];
+ sp_digit a[128];
+ sp_digit d[64];
+ sp_digit m[64];
#else
sp_digit* d = NULL;
sp_digit* a;
@@ -5712,14 +5922,17 @@ extern sp_digit sp_4096_cond_add_avx2_32(sp_digit* r, const sp_digit* a, const s
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
* an array is too long and MEMORY_E when dynamic memory allocation fails.
*/
-int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
+int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
+ const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
+ const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
{
#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
sp_digit ad[64 * 2];
- sp_digit pd[32], qd[32], dpd[32];
- sp_digit tmpad[64], tmpbd[64];
+ sp_digit pd[32];
+ sp_digit qd[32];
+ sp_digit dpd[32];
+ sp_digit tmpad[64];
+ sp_digit tmpbd[64];
#else
sp_digit* t = NULL;
#endif
@@ -5859,7 +6072,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
return err;
}
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
+#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */
#endif /* WOLFSSL_HAVE_SP_RSA */
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
@@ -5879,17 +6092,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = 64;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -5902,14 +6117,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 64; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -5936,10 +6153,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
+int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
+ mp_int* res)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
#ifdef HAVE_INTEL_AVX2
word32 cpuid_flags = cpuid_get_flags();
@@ -5999,10 +6219,12 @@ static int sp_4096_mod_exp_2_avx2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6041,34 +6263,34 @@ static int sp_4096_mod_exp_2_avx2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_4096_lshift_64(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -6122,10 +6344,12 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
sp_digit* norm;
sp_digit* tmp;
sp_digit mp = 1;
- sp_digit n, o;
+ sp_digit n;
+ sp_digit o;
sp_digit mask;
int i;
- int c, y;
+ int c;
+ byte y;
int err = MP_OKAY;
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6164,34 +6388,34 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
if (c < 0) {
/* Number of bits in top word is less than number needed. */
c = -c;
- y = (int)(n << c);
+ y = (byte)(n << c);
n = e[i--];
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)(n >> c);
+ y = (byte)(n >> c);
n <<= 64 - c;
}
sp_4096_lshift_64(r, norm, y);
- for (; i>=0 || c>=6; ) {
+ while ((i >= 0) || (c >= 6)) {
if (c == 0) {
n = e[i--];
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n <<= 6;
c = 58;
}
else if (c < 6) {
- y = (int)(n >> 58);
+ y = (byte)(n >> 58);
n = e[i--];
c = 6 - c;
- y |= (int)(n >> (64 - c));
+ y |= (byte)(n >> (64 - c));
n <<= c;
c = 64 - c;
}
else {
- y = (int)((n >> 58) & 0x3f);
+ y = (byte)((n >> 58) & 0x3f);
n <<= 6;
c -= 6;
}
@@ -6239,11 +6463,13 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
* returns 0 on success, MP_READ_E if there are too many bytes in an array
* and MEMORY_E if memory allocation fails.
*/
-int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
+int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
+ const mp_int* mod, byte* out, word32* outLen)
{
int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
+ sp_digit b[128];
+ sp_digit e[64];
+ sp_digit m[64];
sp_digit* r = b;
word32 i;
#ifdef HAVE_INTEL_AVX2
@@ -6288,6 +6514,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
sp_4096_to_bin(r, out);
*outLen = 512;
for (i=0; i<512 && out[i] == 0; i++) {
+ /* Search for first non-zero. */
}
*outLen -= i;
XMEMMOVE(out, out + i, *outLen);
@@ -6298,19 +6525,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
return err;
}
#endif
-#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
+#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
#endif /* WOLFSSL_SP_4096 */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
/* Point structure to use. */
typedef struct sp_point_256 {
+ /* X ordinate of point. */
sp_digit x[2 * 4];
+ /* Y ordinate of point. */
sp_digit y[2 * 4];
+ /* Z ordinate of point. */
sp_digit z[2 * 4];
+ /* Indicates point is at infinity. */
int infinity;
} sp_point_256;
@@ -6382,7 +6613,19 @@ static const sp_digit p256_b[4] = {
};
#endif
-static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p)
+extern void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b);
+extern void sp_256_sqr_4(sp_digit* r, const sp_digit* a);
+extern sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b);
+extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b);
+/* Create a new point.
+ *
+ * heap [in] Buffer to allocate dynamic memory from.
+ * sp [in] Data for point - only if not allocating.
+ * p [out] New point.
+ * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
+ */
+static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp,
+ sp_point_256** p)
{
int ret = MP_OKAY;
(void)heap;
@@ -6407,6 +6650,12 @@ static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p)
#endif
+/* Free the point.
+ *
+ * p [in,out] Point to free.
+ * clear [in] Indicates whether to zeroize point.
+ * heap [in] Buffer from which dynamic memory was allocate from.
+ */
static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap)
{
#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
@@ -6419,7 +6668,7 @@ static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap)
}
#else
/* Clear point data if requested. */
- if (clear != 0) {
+ if ((p != NULL) && (clear != 0)) {
XMEMSET(p, 0, sizeof(*p));
}
#endif
@@ -6510,7 +6759,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#elif DIGIT_BIT > 64
- int i, j = 0;
+ int i;
+ int j = 0;
word32 s = 0;
r[0] = 0;
@@ -6544,7 +6794,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
r[j] = 0;
}
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
@@ -6580,7 +6832,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
* p Point of type sp_point_256 (result).
* pm Point of type ecc_point.
*/
-static void sp_256_point_from_ecc_point_4(sp_point_256* p, const ecc_point* pm)
+static void sp_256_point_from_ecc_point_4(sp_point_256* p,
+ const ecc_point* pm)
{
XMEMSET(p->x, 0, sizeof(p->x));
XMEMSET(p->y, 0, sizeof(p->y));
@@ -6607,17 +6860,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = 4;
mp_clamp(r);
#elif DIGIT_BIT < 64
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 4; i++) {
r->dp[j] |= (mp_digit)(a[i] << s);
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
s = DIGIT_BIT - s;
r->dp[++j] = (mp_digit)(a[i] >> s);
while (s + DIGIT_BIT <= 64) {
s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
if (s == SP_WORD_SIZE) {
r->dp[j] = 0;
}
@@ -6630,14 +6885,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r)
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
mp_clamp(r);
#else
- int i, j = 0, s = 0;
+ int i;
+ int j = 0;
+ int s = 0;
r->dp[0] = 0;
for (i = 0; i < 4; i++) {
r->dp[j] |= ((mp_digit)a[i]) << s;
if (s + 64 >= DIGIT_BIT) {
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
+ r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
#endif
s = DIGIT_BIT - s;
r->dp[++j] = a[i] >> s;
@@ -6698,7 +6955,7 @@ static void sp_256_mont_sqr_n_4(sp_digit* r, const sp_digit* a, int n,
}
}
-#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
+#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
#ifdef WOLFSSL_SP_SMALL
/* Mod-2 for the P256 curve. */
static const uint64_t p256_mod_minus_2[4] = {
@@ -6784,7 +7041,6 @@ extern int64_t sp_256_cmp_4(const sp_digit* a, const sp_digit* b);
#define sp_256_norm_4(a)
extern sp_digit sp_256_cond_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m);
-extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b);
#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4
extern void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, sp_digit mp);
@@ -6794,7 +7050,8 @@ extern void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, sp_digit mp);
* p Montgomery form projective coordinate point.
* t Temporary ordinate data.
*/
-static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t)
+static void sp_256_map_4(sp_point_256* r, const sp_point_256* p,
+ sp_digit* t)
{
sp_digit* t1 = t;
sp_digit* t2 = t + 2*4;
@@ -6831,7 +7088,7 @@ static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t)
}
extern void sp_256_mont_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m);
-extern void sp_256_mont_dbl_4(const sp_digit* r, const sp_digit* a, const sp_digit* m);
+extern void sp_256_mont_dbl_4(sp_digit* r, const sp_digit* a, const sp_digit* m);
extern void sp_256_mont_tpl_4(sp_digit* r, const sp_digit* a, const sp_digit* m);
extern void sp_256_mont_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m);
extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m);
@@ -7037,7 +7294,8 @@ static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_d
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, sp_digit* t)
+static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n,
+ sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*4;
@@ -7340,8 +7598,8 @@ static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
}
#endif /* WOLFSSL_SP_NONBLOCK */
-static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q,
- sp_digit* t)
+static void sp_256_proj_point_add_4(sp_point_256* r,
+ const sp_point_256* p, const sp_point_256* q, sp_digit* t)
{
const sp_point_256* ap[2];
sp_point_256* rp[2];
@@ -7434,8 +7692,8 @@ static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, cons
* n Number of times to double
* t Temporary ordinate data.
*/
-static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* p,
- int n, int m, sp_digit* t)
+static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r,
+ const sp_point_256* p, int n, int m, sp_digit* t)
{
sp_digit* w = t;
sp_digit* a = t + 2*4;
@@ -7446,6 +7704,7 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256*
sp_digit* y = r[(1< .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sp_Pairing_x64_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit qx_px[2 * 16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ qx_px = td + 8 * 16 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+
+ sp_1024_mont_add_16(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_16(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_16(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* h = t + 8 * 16;
+ sp_digit* r = t + 10 * 16;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_16(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_16(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_16(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_16(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_16(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_16(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_16(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_16(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_16(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_16(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_16(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_16(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_16(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_16(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_16(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_16(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_16(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_16(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_16(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_16(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 16;
+ sp_digit* pz2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* l = t + 8 * 16;
+ sp_digit* ty = t + 10 * 16;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_16(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_16(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_16(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_16(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_16(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_16(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_16(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_16(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_16(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_16(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_16(p->y, p->y, p1024_mod);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_x64_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef HAVE_INTEL_AVX2
+/* Multiply p* by q* in projective co-ordinates.
+ *
+ * p.x' = (p.x * q.x) - (p.y * q.y)
+ * p.y' = (p.x * q.y) + (p.y * q.x)
+ * But applying Karatsuba:
+ * v0 = p.x * q.x
+ * v1 = p.y * q.y
+ * p.x' = v0 - v1
+ * p.y' = (px + py) * (qx + qy) - v0 - v1
+ *
+ * px [in,out] A single precision integer - X ordinate of number to multiply.
+ * py [in,out] A single precision integer - Y ordinate of number to multiply.
+ * qx [in] A single precision integer - X ordinate of number of
+ * multiplier.
+ * qy [in] A single precision integer - Y ordinate of number of
+ * multiplier.
+ * t [in] Two single precision integers - temps.
+ */
+static void sp_1024_proj_mul_avx2_16(sp_digit* px, sp_digit* py,
+ const sp_digit* qx, const sp_digit* qy, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+
+ /* t1 = px + py */
+ sp_1024_mont_add_avx2_16(t1, px, py, p1024_mod);
+ /* t2 = qx + qy */
+ sp_1024_mont_add_avx2_16(t2, qx, qy, p1024_mod);
+ /* t2 = (px + py) * (qx + qy) */
+ sp_1024_mont_mul_avx2_16(t2, t1, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = py * qy */
+ sp_1024_mont_mul_avx2_16(t1, py, qy, p1024_mod, p1024_mp_mod);
+ /* t2 = (px + py) * (qx + qy) - (py * qy) */
+ sp_1024_mont_sub_avx2_16(t2, t2, t1, p1024_mod);
+ /* px = px * qx */
+ sp_1024_mont_mul_avx2_16(px, px, qx, p1024_mod, p1024_mp_mod);
+ /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */
+ sp_1024_mont_sub_avx2_16(py, t2, px, p1024_mod);
+ /* px = (px * qx) - (py * qy)*/
+ sp_1024_mont_sub_avx2_16(px, px, t1, p1024_mod);
+}
+
+#ifndef WOLFSSL_SP_SMALL
+/*
+ * Convert point from projective to affine but keep in Montgomery form.
+ *
+ * p [in,out] Point to convert.
+ * t [in] Temporary numbers: 2.
+ */
+static void sp_1024_mont_map_avx2_16(sp_point_1024* p, sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+
+ sp_1024_mont_inv_avx2_16(t1, p->z, t2);
+ sp_1024_mont_sqr_avx2_16(t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_avx2_16(t1, t2, t1, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_avx2_16(p->x, p->x, t2, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_mul_avx2_16(p->y, p->y, t1, p1024_mod, p1024_mp_mod);
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 16);
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+/*
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2
+ * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 8 * p.y^2 * p.x
+ * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4
+ * p'.z = 2 * p.y * p.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_avx2_16(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 16;
+ sp_digit* pz2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* l = t + 8 * 16;
+ sp_digit* ty = t + 10 * 16;
+
+ /* v = v^2 */
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_avx2_16(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_avx2_16(ty, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_avx2_16(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_avx2_16(t1, l, ty, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_avx2_16(l, t1, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_avx2_16(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_avx2_16(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* r.y = 2 * p.y */
+ sp_1024_mont_dbl_avx2_16(ry, p->y, p1024_mod);
+ /* ty = 4 * p.y ^ 2 */
+ sp_1024_mont_sqr_avx2_16(ty, ry, p1024_mod, p1024_mp_mod);
+ /* t1 = 2 * p.y ^ 2 */
+ sp_1024_div2_avx2_16(t1, ty, p1024_mod);
+ /* r.x -= 2 * (p.y ^ 2) */
+ sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod);
+ /* p'.z = p.y * 2 * p.z */
+ sp_1024_mont_mul_avx2_16(p->z, p->z, ry, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_avx2_16(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = 4 * p.y^2
+ * p'.z = 2 * p.y * p.z
+ */
+ /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */
+ sp_1024_mont_sqr_avx2_16(t1, ty, p1024_mod, p1024_mp_mod);
+ /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */
+ sp_1024_div2_avx2_16(t1, t1, p1024_mod);
+ /* p'.y = 4 * p.y^2 * p.x */
+ sp_1024_mont_mul_avx2_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_avx2_16(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - 4 * p.y^2 * p.x */
+ sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 8 * p.y^2 * p.x */
+ sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod);
+ /* p'.y = 4 * p.y^2 * p.x - p.x' */
+ sp_1024_mont_sub_avx2_16(ty, p->y, p->x, p1024_mod);
+ /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_avx2_16(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */
+ sp_1024_mont_sub_avx2_16(p->y, p->y, t1, p1024_mod);
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Calculations:
+ * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z
+ * r.y = (c.x - p.x * c.z^2) * q.y * c.z
+ * v* = v* * r*
+ * r = p.y * c.z^3 - c.y
+ * c'.x = r^2 + h^3 - 2 * c.x * h^2
+ * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3
+ * c'.z = (c.x - p.x * c.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in] p ECC point - point on E(F_p^2) to add.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] qx_px SP that is a constant value across adds.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_add_one_avx2_16(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px,
+ sp_digit* t)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* h = t + 8 * 16;
+ sp_digit* r = t + 10 * 16;
+
+ /* r.x = (q.x + p.x) * c.y */
+ sp_1024_mont_mul_avx2_16(rx, qx_px, c->y, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_avx2_16(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_avx2_16(h, t1, c->x, p1024_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_avx2_16(ry, p->y, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_avx2_16(t1, h, ry, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */
+ sp_1024_mont_mul_avx2_16(r, ry, t2, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = c.x - p.x * c.z^2 */
+ sp_1024_mont_sub_avx2_16(h, c->x, t1, p1024_mod);
+ /* c'.z = (c.x - p.x * c.z^2) * c.z */
+ sp_1024_mont_mul_avx2_16(c->z, h, c->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */
+ sp_1024_mont_mul_avx2_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = c.x - p.x * c.z^2
+ * r = p.y * c.z^3
+ * c'.z = (c.x - p.x * c.z^2) * c.z
+ */
+
+ /* r = p.y * c.z^3 - c.y */
+ sp_1024_mont_sub_avx2_16(r, r, c->y, p1024_mod);
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_avx2_16(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_avx2_16(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * h^2 */
+ sp_1024_mont_mul_avx2_16(ry, c->x, rx, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_avx2_16(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c->x = r^2 + h^3 */
+ sp_1024_mont_add_avx2_16(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * h^2 */
+ sp_1024_mont_dbl_avx2_16(t1, ry, p1024_mod);
+ /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */
+ sp_1024_mont_sub_avx2_16(c->x, c->x, t1, p1024_mod);
+ /* ry = c'.x - c.x * h^2 */
+ sp_1024_mont_sub_avx2_16(t1, c->x, ry, p1024_mod);
+ /* ry = r * (c'.x - c.x * h^2) */
+ sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * h^3 */
+ sp_1024_mont_mul_avx2_16(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */
+ sp_1024_mont_sub_avx2_16(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static int sp_Pairing_avx2_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err = MP_OKAY;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit* qx_px;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit qx_px[2 * 16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ qx_px = td + 8 * 16 * 2;
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+
+ sp_1024_mont_add_avx2_16(qx_px, q->x, p->x, p1024_mod);
+
+ for (i = 1020; i >= 0; i--) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t);
+
+ if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) {
+ /* Accumulate line into v and add P into C. */
+ sp_1024_accumulate_line_add_one_avx2_16(vx, vy, c, p, q, qx_px, t);
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_avx2_16(vx, vx, t);
+ sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#else
+/*
+ * Calculate gradient of line through C, P and -C-P, accumulate line and
+ * add P to C.
+ *
+ * Both C and P have z ordinates to use in the calculation.
+ *
+ * Calculations:
+ * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
+ * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
+ * v* = v* * r*
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
+ * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] c ECC point - current point on E(F_p^2) to be added
+ * to.
+ * @param [in,out] p ECC point - point on E(F_p^2) to add.
+ * @param [in,out] q ECC point - second point on E(F_P^2).
+ * @param [in,out] t SP temporaries (6 used).
+ * @param [in,out] neg Indicates to use negative P.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+static void sp_1024_accumulate_line_add_n_avx2_16(sp_digit* vx, sp_digit* vy,
+ const sp_point_1024* p, const sp_point_1024* q,
+ sp_point_1024* c, sp_digit* t, int neg)
+{
+ sp_digit* t1 = t;
+ sp_digit* t2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* h = t + 8 * 16;
+ sp_digit* r = t + 10 * 16;
+
+ /* h = p.z^2 */
+ sp_1024_mont_sqr_avx2_16(h, p->z, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 */
+ sp_1024_mont_mul_avx2_16(rx, q->x, h, p1024_mod, p1024_mp_mod);
+ /* rx = q.x * p.z^2 + p.x */
+ sp_1024_mont_add_avx2_16(t2, rx, p->x, p1024_mod);
+ /* c.y = c.y * p.z */
+ sp_1024_mont_mul_avx2_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
+ /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
+ sp_1024_mont_mul_avx2_16(rx, t2, t1, p1024_mod, p1024_mp_mod);
+ /* c.y = c.y * p.z^3 */
+ sp_1024_mont_mul_avx2_16(c->y, t1, h, p1024_mod, p1024_mp_mod);
+ /* t2 = c.z^2 */
+ sp_1024_mont_sqr_avx2_16(t2, c->z, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, q->x, t2, p1024_mod, p1024_mp_mod);
+ /* t1 = q.x * c.z^2 + c.x */
+ sp_1024_mont_add_avx2_16(t1, t1, c->x, p1024_mod);
+ /* c.x = c.x * p.z^2 */
+ sp_1024_mont_mul_avx2_16(c->x, c->x, h, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z */
+ sp_1024_mont_mul_avx2_16(r, p->y, c->z, p1024_mod, p1024_mp_mod);
+ if (neg) {
+ /* r = -p.y * c.z */
+ sp_1024_mont_sub_avx2_16(r, p1024_mod, r, p1024_mod);
+ }
+ /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
+ sp_1024_mont_sub_avx2_16(rx, ry, rx, p1024_mod);
+ /* t1 = p.x * c.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, p->x, t2, p1024_mod, p1024_mp_mod);
+ /* h = p.x * c.z^2 - c.x * p.z^2 */
+ sp_1024_mont_sub_avx2_16(h, t1, c->x, p1024_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
+ sp_1024_mont_mul_avx2_16(t1, h, c->z, p1024_mod, p1024_mp_mod);
+ /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
+ sp_1024_mont_mul_avx2_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
+ /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
+ sp_1024_mont_mul_avx2_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 */
+ sp_1024_mont_mul_avx2_16(t1, r, t2, p1024_mod, p1024_mp_mod);
+ /* r = p.y * c.z^3 - c.y * p.z^3 */
+ sp_1024_mont_sub_avx2_16(r, t1, c->y, p1024_mod);
+ /* v = v * r */
+ sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t);
+
+ /* Add p to c using previously calculated values.
+ * h = p.x * c.z^2 - c.x * p.z^2
+ * r = p.y * c.z^3 - c.y * p.z^3
+ * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
+ */
+
+ /* t1 = r^2 */
+ sp_1024_mont_sqr_avx2_16(t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = h^2 */
+ sp_1024_mont_sqr_avx2_16(rx, h, p1024_mod, p1024_mp_mod);
+ /* ry = c.x * p.z^2 * h^2 */
+ sp_1024_mont_mul_avx2_16(ry, rx, c->x, p1024_mod, p1024_mp_mod);
+ /* t2 = h^3 */
+ sp_1024_mont_mul_avx2_16(t2, rx, h, p1024_mod, p1024_mp_mod);
+ /* c'.x = r^2 - h^3 */
+ sp_1024_mont_sub_avx2_16(c->x, t1, t2, p1024_mod);
+ /* t1 = 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_dbl_avx2_16(t1, ry, p1024_mod);
+ /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
+ sp_1024_mont_sub_avx2_16(c->x, c->x, t1, p1024_mod);
+ /* ry = c.x * p.z^2 * h^2 - c'.x */
+ sp_1024_mont_sub_avx2_16(t1, ry, c->x, p1024_mod);
+ /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
+ sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod);
+ /* t2 = c.y * p.z^3 * h^3 */
+ sp_1024_mont_mul_avx2_16(t1, t2, c->y, p1024_mod, p1024_mp_mod);
+ /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
+ sp_1024_mont_sub_avx2_16(c->y, ry, t1, p1024_mod);
+}
+
+/*
+ * Perform n accumulate doubles and doubles of P.
+ *
+ * py = 2 * p.y
+ *
+ * For each double:
+ * Calculate gradient of line through P, P and [-2]P, accumulate line and
+ * double P.
+ *
+ * Calculations:
+ * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
+ * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
+ * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
+ * v* = v*^2 * r*
+ * p'.x = l^2 - 2 * py^2 * p.x
+ * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
+ * p'.z = py * p.z
+ *
+ * Finally:
+ * p'.y = py' / 2
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in,out] p ECC point - point on E(F_p^2) to double.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] n Number of times to double.
+ * @param [in] t SP temporaries (6 used).
+ */
+static void sp_1024_accumulate_line_dbl_n_avx2_16(sp_digit* vx, sp_digit* vy,
+ sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 16;
+ sp_digit* pz2 = t + 2 * 16;
+ sp_digit* rx = t + 4 * 16;
+ sp_digit* ry = t + 6 * 16;
+ sp_digit* l = t + 8 * 16;
+ sp_digit* ty = t + 10 * 16;
+ int i;
+
+ /* py = 2 * p.y */
+ sp_1024_mont_dbl_avx2_16(p->y, p->y, p1024_mod);
+
+ for (i = 0; i < n; i++) {
+ /* v = v^2 */
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ /* pz2 = p.z^2 */
+ sp_1024_mont_sqr_avx2_16(pz2, p->z, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + p.z^2 */
+ sp_1024_mont_add_avx2_16(t1, p->x, pz2, p1024_mod);
+ /* l = p.x - p.z^2 */
+ sp_1024_mont_sub_avx2_16(l, p->x, pz2, p1024_mod);
+ /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
+ sp_1024_mont_mul_avx2_16(ty, l, t1, p1024_mod, p1024_mp_mod);
+ /* l = 3 * (p.x^2 - p.z^4) */
+ sp_1024_mont_tpl_avx2_16(l, ty, p1024_mod);
+ /* t1 = q.x * p.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x + q.x * p.z^2 */
+ sp_1024_mont_add_avx2_16(t1, p->x, t1, p1024_mod);
+ /* r.x = l * (p.x + q.x * p.z^2) */
+ sp_1024_mont_mul_avx2_16(rx, l, t1, p1024_mod, p1024_mp_mod);
+ /* ty = py ^ 2 */
+ sp_1024_mont_sqr_avx2_16(ty, p->y, p1024_mod, p1024_mp_mod);
+ /* t1 = py ^ 2 / 2 */
+ sp_1024_div2_avx2_16(t1, ty, p1024_mod);
+ /* r.x -= py ^ 2 / 2 */
+ sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod);
+ /* p'.z = py * pz */
+ sp_1024_mont_mul_avx2_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 */
+ sp_1024_mont_mul_avx2_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
+ /* r.y = p'.z * p.z^2 * q.y */
+ sp_1024_mont_mul_avx2_16(ry, t1, q->y, p1024_mod, p1024_mp_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t);
+
+ /* Double point using previously calculated values
+ * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
+ * ty = py^2
+ * p'.z = py * p.z
+ */
+ /* t1 = py^2 ^ 2 = py^4 */
+ sp_1024_mont_sqr_avx2_16(t1, ty, p1024_mod, p1024_mp_mod);
+ /* py' = py^2 * p. x */
+ sp_1024_mont_mul_avx2_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 */
+ sp_1024_mont_sqr_avx2_16(p->x, l, p1024_mod, p1024_mp_mod);
+ /* p'.x = l^2 - py^2 * p.x */
+ sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod);
+ /* p'.x = l^2 - 2 * p.y^2 * p.x */
+ sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod);
+ /* py' = py^2 * p.x - p.x' */
+ sp_1024_mont_sub_avx2_16(ty, p->y, p->x, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l */
+ sp_1024_mont_mul_avx2_16(p->y, ty, l, p1024_mod, p1024_mp_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
+ sp_1024_mont_dbl_avx2_16(p->y, p->y, p1024_mod);
+ /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
+ sp_1024_mont_sub_avx2_16(p->y, p->y, t1, p1024_mod);
+ }
+
+ /* p'.y = py' / 2 */
+ sp_1024_div2_avx2_16(p->y, p->y, p1024_mod);
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_avx2_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+
+ err = sp_1024_point_new_16(NULL, pd, p);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+ pre_p = (sp_point_1024*)(td + 56 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_avx2_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_avx2_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_avx2_16(pre_vx[i], pre_vy[i], c,
+ q, &pre_p[i], t, 0);
+ sp_1024_mont_sub_avx2_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
+ }
+
+ j = sp_1024_order_op[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_avx2_16(vx, vy, c, q,
+ sp_1024_order_op[1], t);
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ sp_1024_accumulate_line_add_n_avx2_16(vx, vy, &pre_p[j], q, c,
+ t, 0);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v and add P into C. */
+ sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ sp_1024_accumulate_line_add_n_avx2_16(vx, vy, &pre_p[j], q, c,
+ t, 1);
+ }
+
+ /* Accumulate line into v and double point n times. */
+ sp_1024_accumulate_line_dbl_n_avx2_16(vx, vy, c, q,
+ sp_1024_order_op[i + 1], t);
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_avx2_16(vx, vx, t);
+ sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_avx2_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#endif /* HAVE_INTEL_AVX2 */
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
+{
+ int err;
+#ifdef HAVE_INTEL_AVX2
+ word32 cpuid_flags = cpuid_get_flags();
+#endif
+
+#ifdef HAVE_INTEL_AVX2
+ if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
+ err = sp_Pairing_avx2_1024(pm, qm, res);
+ }
+ else
+#endif
+ {
+ err = sp_Pairing_x64_1024(pm, qm, res);
+ }
+
+ return err;
+}
+
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+static int sp_Pairing_gen_precomp_x64_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_precomp_x64_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_x64_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* t2 = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_16(l, py, p1024_mod);
+ sp_1024_mont_inv_16(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_16(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_16(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_16(t2, t1, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_16(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_16(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_16(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* c = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_16(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_16(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_16(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_16(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_16(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_16(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_16(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_16(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_16(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 16;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_16(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_16(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_16(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_16(vx, vy, rx, q->y, t);
+}
+
+/* Operations to perform based on order - 1.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pairs: #dbls, add/subtract window value
+ */
+static const signed char sp_1024_order_op_pre[] = {
+ 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
+ -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
+ -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
+ 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
+ -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
+ -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
+ -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
+ -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
+ -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
+ 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
+ -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
+ -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
+ 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
+ -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
+ 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
+ -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
+ 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
+ -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
+ -3, 1,
+};
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+static int sp_Pairing_gen_precomp_x64_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 16 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_16(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_16(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_16(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_16(c, c, t);
+ sp_1024_mont_map_16(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_16(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_16(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_16(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_16(c, c, neg, t);
+ sp_1024_mont_map_16(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_16(c, c, t);
+ sp_1024_mont_map_16(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(neg, 1, NULL);
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_precomp_x64_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_16(vx, vy, t);
+ sp_1024_proj_sqr_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_16(vx, vx, t);
+ sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#ifdef HAVE_INTEL_AVX2
+#ifdef WOLFSSL_SP_SMALL
+/*
+ * Generate table for pairing.
+ *
+ * Small implementation does not use a table - returns 0 length.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ */
+static int sp_Pairing_gen_precomp_avx2_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+
+ if (table == NULL) {
+ *len = 0;
+ err = LENGTH_ONLY_E;
+ }
+ else if (*len != 0) {
+ err = BUFFER_E;
+ }
+
+ (void)*pm;
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Small implementation does not use a table - use the normal implementation.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_precomp_avx2_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ (void)table;
+ (void)len;
+ return sp_Pairing_avx2_1024(pm, qm, res);
+}
+
+#else
+/*
+ * Calc l and c for the point when doubling p.
+ *
+ * l = 3 * (p.x^2 - 1) / (2 * p.y)
+ * c = l * p.x - p.y
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to double.
+ * @param [in] py Y-ordinate of point to double.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_dbl_calc_lc_avx2_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* t2 = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / 2 * p.y */
+ sp_1024_mont_dbl_avx2_16(l, py, p1024_mod);
+ sp_1024_mont_inv_avx2_16(l, l, t);
+
+ /* t1 = p.x^2 */
+ sp_1024_mont_sqr_avx2_16(t1, px, p1024_mod, p1024_mp_mod);
+ /* t1 = p.x - 1 */
+ sp_1024_mont_sub_avx2_16(t1, t1, p1024_norm_mod, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) */
+ sp_1024_mont_dbl_avx2_16(t2, t1, p1024_mod);
+ sp_1024_mont_add_avx2_16(t1, t1, t2, p1024_mod);
+ /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
+ sp_1024_mont_mul_avx2_16(l, l, t1, p1024_mod, p1024_mp_mod);
+ /* t2 = l * p.x */
+ sp_1024_mont_mul_avx2_16(t2, l, px, p1024_mod, p1024_mp_mod);
+ /* c = t2 = l * p.x - p.y */
+ sp_1024_mont_sub_avx2_16(t2, t2, py, p1024_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, t2, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calc l and c when adding p and c.
+ *
+ * l = (c.y - p.y) / (c.x - p.x)
+ * c = (p.x * c.y - cx * p.y) / (cx - p.x)
+ *
+ * @param [out] lr Gradient result - table entry.
+ * @param [out] cr Constant result - table entry.
+ * @param [in] px X-ordinate of point to add.
+ * @param [in] py Y-ordinate of point to add.
+ * @param [in] cx X-ordinate of current point.
+ * @param [in] cy Y-ordinate of current point.
+ * @param [in] t SP temporaries (3 used).
+ */
+static void sp_1024_accum_add_calc_lc_avx2_16(sp_digit* lr, sp_digit* cr,
+ const sp_digit* px, const sp_digit* py, const sp_digit* cx,
+ const sp_digit* cy, sp_digit* t)
+{
+ sp_digit* t1 = t + 0 * 2 * 16;
+ sp_digit* c = t + 2 * 2 * 16;
+ sp_digit* l = t + 4 * 2 * 16;
+
+
+ /* l = 1 / (c.x - p.x) */
+ sp_1024_mont_sub_avx2_16(l, cx, px, p1024_mod);
+ sp_1024_mont_inv_avx2_16(l, l, t);
+
+ /* c = p.x * c.y */
+ sp_1024_mont_mul_avx2_16(c, px, cy, p1024_mod, p1024_mp_mod);
+ /* t1 = c.x * p.y */
+ sp_1024_mont_mul_avx2_16(t1, cx, py, p1024_mod, p1024_mp_mod);
+ /* c = (p.x * c.y) - (c.x * p.y) */
+ sp_1024_mont_sub_avx2_16(c, c, t1, p1024_mod);
+ /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
+ sp_1024_mont_mul_avx2_16(c, c, l, p1024_mod, p1024_mp_mod);
+ /* t1 = c.y - p.y */
+ sp_1024_mont_sub_avx2_16(t1, cy, py, p1024_mod);
+ /* l = (c.y - p.y) / (c.x - p.x) */
+ sp_1024_mont_mul_avx2_16(l, t1, l, p1024_mod, p1024_mp_mod);
+
+ XMEMCPY(lr, l, sizeof(sp_digit) * 16);
+ XMEMCPY(cr, c, sizeof(sp_digit) * 16);
+}
+
+/*
+ * Calculate vx and vy given gradient l and constant c and point q.
+ *
+ * l is a the gradient and is multiplied by q->x.
+ * c is a the constant that is added to the multiplicative result.
+ * q->y is the y-ordinate in result to multiply.
+ *
+ * if dbl
+ * v* = v*^2
+ * r.x = l * q.x + c
+ * r.y = q->y
+ * v* = v* * r*
+ *
+ * @param [in,out] vx X-ordinate of projective value in F*.
+ * @param [in,out] vy Y-ordinate of projective value in F*.
+ * @param [in] l Gradient to multiply with.
+ * @param [in] c Constant to add with.
+ * @param [in] q ECC point - second point on E(F_P^2).
+ * @param [in] t SP temporaries (3 used).
+ * @param [in] dbl Indicates whether this is for doubling. Otherwise
+ * adding.
+ */
+static void sp_1024_accumulate_line_lc_avx2_16(sp_digit* vx, sp_digit* vy,
+ const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
+ sp_digit* t, int dbl)
+{
+ sp_digit* rx = t + 4 * 2 * 16;
+
+ /* v = v^2 */
+ if (dbl) {
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ }
+ /* rx = l * q.x + c */
+ sp_1024_mont_mul_avx2_16(rx, l, q->x, p1024_mod, p1024_mp_mod);
+ sp_1024_mont_add_avx2_16(rx, rx, c, p1024_mod);
+ /* v = v^2 * r */
+ sp_1024_proj_mul_avx2_16(vx, vy, rx, q->y, t);
+}
+
+
+/*
+ * Generate table for pairing.
+ *
+ * Calculate the graident (l) and constant (c) at each step of the way.
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * LENGTH_ONLY_E when table is NULL and only length returned.
+ * BUFFER_E when len is too small.
+ * MEMORY_E when dynamic memory allocation fauls.
+ */
+static int sp_Pairing_gen_precomp_avx2_1024(const ecc_point* pm, byte* table,
+ word32* len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_point_1024* pre_p;
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_point_1024 pre_p[16];
+ sp_point_1024 pd;
+ sp_point_1024 cd;
+ sp_point_1024 negd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* c = NULL;
+ sp_point_1024* neg = NULL;
+ int i;
+ int j;
+ int k;
+ sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
+
+ if (table == NULL) {
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ err = LENGTH_ONLY_E;
+ }
+
+ if ((err == MP_OKAY) &&
+ (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, negd, neg);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ pre_p = (sp_point_1024*)(td + 6 * 16 * 2);
+#endif
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+
+ err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
+ neg->infinity = 0;
+ c->infinity = 0;
+
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
+ /* [2]P for adding */
+ sp_1024_proj_point_dbl_avx2_16(c, p, t);
+
+ /* 1, 3, ... */
+ for (i = 1; i < 16; i++) {
+ sp_1024_proj_point_add_avx2_16(&pre_p[i], &pre_p[i-1], c, t);
+ sp_1024_mont_map_avx2_16(&pre_p[i], t);
+ }
+
+ k = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
+
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ sp_1024_accum_dbl_calc_lc_avx2_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_avx2_16(c, c, t);
+ sp_1024_mont_map_avx2_16(c, t);
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ sp_1024_accum_add_calc_lc_avx2_16(precomp[k].x, precomp[k].y,
+ pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_avx2_16(c, c, &pre_p[j/2], t);
+ sp_1024_mont_map_avx2_16(c, t);
+ }
+ else {
+ XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
+ sp_1024_mont_sub_avx2_16(neg->y, p1024_mod, pre_p[-j / 2].y,
+ p1024_mod);
+ XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
+
+ sp_1024_accum_add_calc_lc_avx2_16(precomp[k].x, precomp[k].y,
+ neg->x, neg->y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_add_avx2_16(c, c, neg, t);
+ sp_1024_mont_map_avx2_16(c, t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ sp_1024_accum_dbl_calc_lc_avx2_16(precomp[k].x, precomp[k].y, c->x, c->y, t);
+ k++;
+ sp_1024_proj_point_dbl_avx2_16(c, c, t);
+ sp_1024_mont_map_avx2_16(c, t);
+ }
+ }
+
+ *len = sizeof(sp_table_entry_1024) * 1167;
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(neg, 1, NULL);
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * Sliding window. Start at bottom and stop when bottom bit is one.
+ * Subtract if top bit in window is one.
+ * Width of 6 bits.
+ * Pre-generate values in window (1, 3, ...) - only V.
+ * Table contains all gradient l and a constant for each point on the path.
+ *
+ * @param [in] pm First point on E(F_p)[q].
+ * @param [in] qm Second point on E(F_p)[q].
+ * @param [in] res Result of calculation.
+ * @param [in] table Precomputed table of values.
+ * @param [in] len Length of precomputed table of values in bytes.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int sp_Pairing_precomp_avx2_1024(const ecc_point* pm, const ecc_point* qm,
+ mp_int* res, const byte* table, word32 len)
+{
+ int err = 0;
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* td = NULL;
+ sp_digit* t;
+ sp_digit* vx;
+ sp_digit* vy;
+ sp_digit (*pre_vx)[32];
+ sp_digit (*pre_vy)[32];
+ sp_digit (*pre_nvy)[32];
+#else
+ sp_digit t[6 * 2 * 16];
+ sp_digit vx[2 * 16];
+ sp_digit vy[2 * 16];
+ sp_digit pre_vx[16][32];
+ sp_digit pre_vy[16][32];
+ sp_digit pre_nvy[16][32];
+ sp_point_1024 pd;
+ sp_point_1024 qd;
+ sp_point_1024 cd;
+#endif
+ sp_point_1024* p = NULL;
+ sp_point_1024* q = NULL;
+ sp_point_1024* c = NULL;
+ sp_digit* r = NULL;
+ int i;
+ int j;
+ int k;
+ const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
+
+ if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
+ err = BUFFER_E;
+ }
+
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, pd, p);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, qd, q);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(NULL, cd, c);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY) {
+ td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (td == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t = td;
+ vx = td + 6 * 16 * 2;
+ vy = td + 7 * 16 * 2;
+ pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2);
+ pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2);
+ pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2);
+#endif
+ r = vy;
+
+ sp_1024_point_from_ecc_point_16(p, pm);
+ sp_1024_point_from_ecc_point_16(q, qm);
+
+ err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod);
+ }
+ if (err == MP_OKAY) {
+ /* Generate pre-computation table: 1, 3, ... , 31 */
+ XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16);
+ pre_vx[0][0] = 1;
+ XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_mont_sub_avx2_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
+
+ /* [2]P for adding */
+ XMEMCPY(c, p, sizeof(sp_point_1024));
+ XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16);
+ vx[0] = 1;
+ XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16);
+ sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t);
+
+ /* 3, 5, ... */
+ for (i = 1; i < 16; i++) {
+ XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16);
+ sp_1024_proj_mul_avx2_16(pre_vx[i], pre_vy[i], vx, vy, t);
+ sp_1024_accumulate_line_add_n_avx2_16(pre_vx[i], pre_vy[i], c,
+ q, p, t, 0);
+ sp_1024_mont_sub_avx2_16(pre_nvy[i], p1024_mod, pre_vy[i],
+ p1024_mod);
+ }
+
+ XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16);
+ c->infinity = 0;
+ j = sp_1024_order_op_pre[0] / 2;
+ XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16);
+ XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16);
+
+ k = 0;
+ for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+
+ for (i = 2; i < 290; i += 2) {
+ sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 0);
+ k++;
+
+ j = sp_1024_order_op_pre[i];
+ if (j > 0) {
+ j /= 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_vy[j], t);
+ }
+ else {
+ j = -j / 2;
+ /* Accumulate line into v. */
+ sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_nvy[j], t);
+ }
+
+ for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
+ /* Accumulate line into v and double point. */
+ sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x,
+ precomp[k].y, q, t, 1);
+ k++;
+ }
+ }
+
+ /* Final exponentiation */
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+ sp_1024_proj_sqr_avx2_16(vx, vy, t);
+
+ /* Convert from PF_p[q] to F_p */
+ sp_1024_mont_inv_avx2_16(vx, vx, t);
+ sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod);
+ XMEMSET(r + 16, 0, sizeof(sp_digit) * 16);
+ sp_1024_mont_reduce_avx2_16(r, p1024_mod, p1024_mp_mod);
+
+ err = sp_1024_to_mp(r, res);
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (td != NULL) {
+ XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ sp_1024_point_free_16(c, 1, NULL);
+ sp_1024_point_free_16(q, 1, NULL);
+ sp_1024_point_free_16(p, 1, NULL);
+ return err;
+}
+
+#endif /* WOLFSSL_SP_SMALL */
+#endif /* HAVE_INTEL_AVX2 */
+/*
+ * Generate table for pairing.
+ *
+ * pm [in] Point to generate table for.
+ * table [in] Generated table.
+ * len [in,out] On in, the size of the buffer.
+ * On out, length of table generated.
+ * @return 0 on success.
+ * Otherwise failure.
+ */
+int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, word32* len)
+{
+ int err;
+#ifdef HAVE_INTEL_AVX2
+ word32 cpuid_flags = cpuid_get_flags();
+#endif
+
+#ifdef HAVE_INTEL_AVX2
+ if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
+ err = sp_Pairing_gen_precomp_avx2_1024(pm, table, len);
+ }
+ else
+#endif
+ {
+ err = sp_Pairing_gen_precomp_x64_1024(pm, table, len);
+ }
+
+ return err;
+}
+
+/*
+ * Calculate r = pairing .
+ *
+ * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
+ *
+ * @param [in] key SAKKE key.
+ * @param [in] p First point on E(F_p)[q].
+ * @param [in] q Second point on E(F_p)[q].
+ * @param [in] r Result of calculation.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ * @return Other -ve value on internal failure.
+ */
+int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res,
+ const byte* table, word32 len)
+{
+ int err;
+#ifdef HAVE_INTEL_AVX2
+ word32 cpuid_flags = cpuid_get_flags();
+#endif
+
+#ifdef HAVE_INTEL_AVX2
+ if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
+ err = sp_Pairing_precomp_avx2_1024(pm, qm, res, table, len);
+ }
+ else
+#endif
+ {
+ err = sp_Pairing_precomp_x64_1024(pm, qm, res, table, len);
+ }
+
+ return err;
+}
+
+/* Returns 1 if the number of zero.
+ * Implementation is constant time.
+ *
+ * a Number to check.
+ * returns 1 if the number is zero and 0 otherwise.
+ */
+static int sp_1024_iszero_16(const sp_digit* a)
+{
+ return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
+ a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15]) == 0;
+}
+
+#ifdef HAVE_ECC_CHECK_KEY
+extern void sp_1024_from_bin_bswap(sp_digit* r, int size, const byte* a, int n);
+extern void sp_1024_from_bin_movbe(sp_digit* r, int size, const byte* a, int n);
+/* Read big endian unsigned byte array into r.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
+{
+#ifndef NO_MOVBE_SUPPORT
+ word32 cpuid_flags = cpuid_get_flags();
+
+ if (IS_INTEL_MOVBE(cpuid_flags)) {
+ sp_1024_from_bin_movbe(r, size, a, n);
+ }
+ else
+#endif
+ {
+ sp_1024_from_bin_bswap(r, size, a, n);
+ }
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * point EC point.
+ * heap Heap to use if dynamically allocating.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+static int sp_1024_ecc_is_point_16(const sp_point_1024* point,
+ void* heap)
+{
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit* d = NULL;
+#else
+ sp_digit t1d[2*16];
+ sp_digit t2d[2*16];
+#endif
+ sp_digit* t1;
+ sp_digit* t2;
+ int64_t n;
+ int err = MP_OKAY;
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC);
+ if (d == NULL) {
+ err = MEMORY_E;
+ }
+#endif
+ (void)heap;
+
+ if (err == MP_OKAY) {
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ t1 = d + 0 * 16;
+ t2 = d + 2 * 16;
+#else
+ t1 = t1d;
+ t2 = t2d;
+#endif
+
+ sp_1024_sqr_16(t1, point->y);
+ (void)sp_1024_mod_16(t1, t1, p1024_mod);
+ sp_1024_sqr_16(t2, point->x);
+ (void)sp_1024_mod_16(t2, t2, p1024_mod);
+ sp_1024_mul_16(t2, t2, point->x);
+ (void)sp_1024_mod_16(t2, t2, p1024_mod);
+ (void)sp_1024_sub_16(t2, p1024_mod, t2);
+ sp_1024_mont_add_16(t1, t1, t2, p1024_mod);
+
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+ sp_1024_mont_add_16(t1, t1, point->x, p1024_mod);
+
+ n = sp_1024_cmp_16(t1, p1024_mod);
+ sp_1024_cond_sub_16(t1, t1, p1024_mod, 0 - ((n >= 0) ?
+ (sp_digit)1 : (sp_digit)0));
+ sp_1024_norm_16(t1);
+ if (!sp_1024_iszero_16(t1)) {
+ err = MP_VAL;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (d != NULL) {
+ XFREE(d, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+
+ return err;
+}
+
+/* Check that the x and y oridinates are a valid point on the curve.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve and MP_OKAY otherwise.
+ */
+int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_point_1024 pubd;
+#endif
+ sp_point_1024* pub;
+ byte one[1] = { 1 };
+ int err;
+
+ err = sp_1024_point_new_16(NULL, pubd, pub);
+ if (err == MP_OKAY) {
+ sp_1024_from_mp(pub->x, 16, pX);
+ sp_1024_from_mp(pub->y, 16, pY);
+ sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one));
+
+ err = sp_1024_ecc_is_point_16(pub, NULL);
+ }
+
+ sp_1024_point_free_16(pub, 0, NULL);
+
+ return err;
+}
+
+/* Check that the private scalar generates the EC point (px, py), the point is
+ * on the curve and the point has the correct order.
+ *
+ * pX X ordinate of EC point.
+ * pY Y ordinate of EC point.
+ * privm Private scalar that generates EC point.
+ * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
+ * not on the curve, ECC_INF_E if the point does not have the correct order,
+ * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
+ * MP_OKAY otherwise.
+ */
+int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
+ const mp_int* privm, void* heap)
+{
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ sp_digit privd[16];
+ sp_point_1024 pubd;
+ sp_point_1024 pd;
+#endif
+ sp_digit* priv = NULL;
+ sp_point_1024* pub;
+ sp_point_1024* p = NULL;
+ byte one[1] = { 1 };
+ int err;
+#ifdef HAVE_INTEL_AVX2
+ word32 cpuid_flags = cpuid_get_flags();
+#endif
+
+ err = sp_1024_point_new_16(heap, pubd, pub);
+ if (err == MP_OKAY) {
+ err = sp_1024_point_new_16(heap, pd, p);
+ }
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (err == MP_OKAY && privm) {
+ priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap,
+ DYNAMIC_TYPE_ECC);
+ if (priv == NULL) {
+ err = MEMORY_E;
+ }
+ }
+#endif
+
+ /* Quick check the lengs of public key ordinates and private key are in
+ * range. Proper check later.
+ */
+ if ((err == MP_OKAY) && ((mp_count_bits(pX) > 1024) ||
+ (mp_count_bits(pY) > 1024) ||
+ ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC)
+ priv = privd;
+#endif
+
+ sp_1024_from_mp(pub->x, 16, pX);
+ sp_1024_from_mp(pub->y, 16, pY);
+ sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one));
+ if (privm)
+ sp_1024_from_mp(priv, 16, privm);
+
+ /* Check point at infinitiy. */
+ if ((sp_1024_iszero_16(pub->x) != 0) &&
+ (sp_1024_iszero_16(pub->y) != 0)) {
+ err = ECC_INF_E;
+ }
+ }
+
+ /* Check range of X and Y */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_16(pub->x, p1024_mod) >= 0) ||
+ (sp_1024_cmp_16(pub->y, p1024_mod) >= 0))) {
+ err = ECC_OUT_OF_RANGE_E;
+ }
+
+ if (err == MP_OKAY) {
+ /* Check point is on curve */
+ err = sp_1024_ecc_is_point_16(pub, heap);
+ }
+
+ if (err == MP_OKAY) {
+ /* Point * order = infinity */
+#ifdef HAVE_INTEL_AVX2
+ if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
+ err = sp_1024_ecc_mulmod_avx2_16(p, pub, p1024_order, 1, 1, heap);
+ else
+#endif
+ err = sp_1024_ecc_mulmod_16(p, pub, p1024_order, 1, 1, heap);
+ }
+ /* Check result is infinity */
+ if ((err == MP_OKAY) && ((sp_1024_iszero_16(p->x) == 0) ||
+ (sp_1024_iszero_16(p->y) == 0))) {
+ err = ECC_INF_E;
+ }
+
+ if (privm) {
+ if (err == MP_OKAY) {
+ /* Base * private = point */
+#ifdef HAVE_INTEL_AVX2
+ if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
+ err = sp_1024_ecc_mulmod_base_avx2_16(p, priv, 1, 1, heap);
+ else
+#endif
+ err = sp_1024_ecc_mulmod_base_16(p, priv, 1, 1, heap);
+ }
+ /* Check result is public key */
+ if ((err == MP_OKAY) &&
+ ((sp_1024_cmp_16(p->x, pub->x) != 0) ||
+ (sp_1024_cmp_16(p->y, pub->y) != 0))) {
+ err = ECC_PRIV_KEY_E;
+ }
+ }
+
+#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
+ if (priv != NULL) {
+ XFREE(priv, heap, DYNAMIC_TYPE_ECC);
+ }
+#endif
+ sp_1024_point_free_16(p, 0, heap);
+ sp_1024_point_free_16(pub, 0, heap);
+
+ return err;
+}
+#endif
+#endif /* WOLFSSL_SP_1024 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_SP_X86_64_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
+#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
diff --git a/wolfcrypt/src/sp_x86_64_asm.S b/wolfcrypt/src/sp_x86_64_asm.S
index feb766fbf..ce112f6f1 100644
--- a/wolfcrypt/src/sp_x86_64_asm.S
+++ b/wolfcrypt/src/sp_x86_64_asm.S
@@ -1,6 +1,6 @@
/* sp_x86_64_asm
*
- * Copyright (C) 2006-2020 wolfSSL Inc.
+ * Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -122,6 +122,7 @@ L_2048_from_bin_bswap_zero_end:
#ifndef __APPLE__
.size sp_2048_from_bin_bswap,.-sp_2048_from_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Read big endian unsigned byte array into r.
* Uses the movbe instruction which is an optional instruction.
*
@@ -207,6 +208,7 @@ L_2048_from_bin_movbe_zero_end:
#ifndef __APPLE__
.size sp_2048_from_bin_movbe,.-sp_2048_from_bin_movbe
#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 256
* Uses the bswap instruction.
@@ -326,6 +328,7 @@ _sp_2048_to_bin_bswap:
#ifndef __APPLE__
.size sp_2048_to_bin_bswap,.-sp_2048_to_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 256
* Uses the movbe instruction which is optional.
@@ -413,6 +416,7 @@ _sp_2048_to_bin_movbe:
#ifndef __APPLE__
.size sp_2048_to_bin_movbe,.-sp_2048_to_bin_movbe
#endif /* __APPLE__ */
+#endif /* NO_MOVBE_SUPPORT */
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -3190,6 +3194,7 @@ _sp_2048_mul_avx2_16:
cmovne %rdi, %rbx
cmpq %rdi, %rbp
cmove %rsp, %rbx
+ addq $0x80, %rdi
xorq %r14, %r14
movq (%rsi), %rdx
# A[0] * B[0]
@@ -3258,7 +3263,7 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adcxq %r14, %r13
movq %r8, 120(%rbx)
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
movq 8(%rsi), %rdx
movq 8(%rbx), %r9
movq 16(%rbx), %r10
@@ -3335,7 +3340,7 @@ _sp_2048_mul_avx2_16:
movq %r10, 96(%rbx)
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
+ movq (%rdi), %r9
# A[1] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r11
@@ -3360,8 +3365,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r9, 128(%rdi)
- movq %r10, 136(%rdi)
+ movq %r9, (%rdi)
+ movq %r10, 8(%rdi)
movq 16(%rsi), %rdx
movq 16(%rbx), %r10
movq 24(%rbx), %r11
@@ -3437,8 +3442,8 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r12
movq %r11, 104(%rbx)
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[2] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r12
@@ -3455,7 +3460,7 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[2] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
movq %r14, %r11
adcxq %rax, %r10
adoxq %rcx, %r11
@@ -3463,8 +3468,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r10, 136(%rdi)
- movq %r11, 144(%rdi)
+ movq %r10, 8(%rdi)
+ movq %r11, 16(%rdi)
movq 24(%rsi), %rdx
movq 24(%rbx), %r11
movq 32(%rbx), %r12
@@ -3539,9 +3544,9 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r12
adoxq %rcx, %r8
movq %r12, 112(%rbx)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
# A[3] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r8
@@ -3553,12 +3558,12 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[3] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[3] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
movq %r14, %r12
adcxq %rax, %r11
adoxq %rcx, %r12
@@ -3566,8 +3571,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r11, 144(%rdi)
- movq %r12, 152(%rdi)
+ movq %r11, 16(%rdi)
+ movq %r12, 24(%rdi)
movq 32(%rsi), %rdx
movq 32(%rbx), %r12
movq 40(%rbx), %r8
@@ -3621,7 +3626,7 @@ _sp_2048_mul_avx2_16:
movq 104(%rbx), %r11
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
+ movq (%rdi), %r9
# A[4] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -3642,26 +3647,26 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r8
adoxq %rcx, %r9
movq %r8, 120(%rbx)
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
# A[4] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[4] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[4] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[4] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
movq %r14, %r8
adcxq %rax, %r12
adoxq %rcx, %r8
@@ -3669,8 +3674,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r12, 152(%rdi)
- movq %r8, 160(%rdi)
+ movq %r12, 24(%rdi)
+ movq %r8, 32(%rdi)
movq 40(%rsi), %rdx
movq 40(%rbx), %r8
movq 48(%rbx), %r9
@@ -3723,8 +3728,8 @@ _sp_2048_mul_avx2_16:
movq %r10, 96(%rbx)
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[5] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r11
@@ -3744,27 +3749,27 @@ _sp_2048_mul_avx2_16:
movq %r8, 120(%rbx)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
# A[5] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[5] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[5] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[5] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
movq %r14, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
@@ -3772,8 +3777,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r8, 160(%rdi)
- movq %r9, 168(%rdi)
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
movq 48(%rsi), %rdx
movq 48(%rbx), %r9
movq 56(%rbx), %r10
@@ -3825,9 +3830,9 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r12
movq %r11, 104(%rbx)
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
# A[6] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r12
@@ -3844,30 +3849,30 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[6] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
- movq %r10, 136(%rdi)
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[6] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r11
adoxq %rcx, %r12
# A[6] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[6] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[6] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
movq %r14, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
@@ -3875,8 +3880,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r9, 168(%rdi)
- movq %r10, 176(%rdi)
+ movq %r9, 40(%rdi)
+ movq %r10, 48(%rdi)
movq 56(%rsi), %rdx
movq 56(%rbx), %r10
movq 64(%rbx), %r11
@@ -3927,10 +3932,10 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r12
adoxq %rcx, %r8
movq %r12, 112(%rbx)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
# A[7] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r8
@@ -3942,35 +3947,35 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[7] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[7] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
- movq %r11, 144(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
# A[7] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r12
adoxq %rcx, %r8
# A[7] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[7] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[7] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
movq %r14, %r11
adcxq %rax, %r10
adoxq %rcx, %r11
@@ -3978,8 +3983,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r10, 176(%rdi)
- movq %r11, 184(%rdi)
+ movq %r10, 48(%rdi)
+ movq %r11, 56(%rdi)
movq 64(%rsi), %rdx
movq 64(%rbx), %r11
movq 72(%rbx), %r12
@@ -4009,7 +4014,7 @@ _sp_2048_mul_avx2_16:
movq 104(%rbx), %r11
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
+ movq (%rdi), %r9
# A[8] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -4030,50 +4035,50 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r8
adoxq %rcx, %r9
movq %r8, 120(%rbx)
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
# A[8] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[8] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[8] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[8] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
- movq %r12, 152(%rdi)
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
+ movq %r12, 24(%rdi)
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
# A[8] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[8] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[8] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[8] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
movq %r14, %r12
adcxq %rax, %r11
adoxq %rcx, %r12
@@ -4081,8 +4086,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r11, 184(%rdi)
- movq %r12, 192(%rdi)
+ movq %r11, 56(%rdi)
+ movq %r12, 64(%rdi)
movq 72(%rsi), %rdx
movq 72(%rbx), %r12
movq 80(%rbx), %r8
@@ -4111,8 +4116,8 @@ _sp_2048_mul_avx2_16:
movq %r10, 96(%rbx)
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[9] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r11
@@ -4132,51 +4137,51 @@ _sp_2048_mul_avx2_16:
movq %r8, 120(%rbx)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[9] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[9] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[9] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[9] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 160(%rdi)
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
- movq 192(%rdi), %r12
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
# A[9] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[9] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[9] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[9] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
movq %r14, %r8
adcxq %rax, %r12
adoxq %rcx, %r8
@@ -4184,8 +4189,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r12, 192(%rdi)
- movq %r8, 200(%rdi)
+ movq %r12, 64(%rdi)
+ movq %r8, 72(%rdi)
movq 80(%rsi), %rdx
movq 80(%rbx), %r8
movq 88(%rbx), %r9
@@ -4213,9 +4218,9 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r12
movq %r11, 104(%rbx)
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
# A[10] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r12
@@ -4232,54 +4237,54 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[10] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
- movq %r10, 136(%rdi)
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
# A[10] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r11
adoxq %rcx, %r12
# A[10] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[10] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[10] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 168(%rdi)
- movq 184(%rdi), %r11
- movq 192(%rdi), %r12
- movq 200(%rdi), %r8
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
# A[10] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[10] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[10] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[10] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r12, 192(%rdi)
+ movq %r12, 64(%rdi)
movq %r14, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
@@ -4287,8 +4292,8 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r8, 200(%rdi)
- movq %r9, 208(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
movq 88(%rsi), %rdx
movq 88(%rbx), %r9
movq 96(%rbx), %r10
@@ -4315,10 +4320,10 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r12
adoxq %rcx, %r8
movq %r12, 112(%rbx)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
# A[11] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r8
@@ -4330,59 +4335,59 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[11] * B[6]
mulx 48(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[11] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
- movq %r11, 144(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
# A[11] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r12
adoxq %rcx, %r8
# A[11] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[11] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[11] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
- movq %r10, 176(%rdi)
- movq 192(%rdi), %r12
- movq 200(%rdi), %r8
- movq 208(%rdi), %r9
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
# A[11] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r11
adoxq %rcx, %r12
# A[11] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[11] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r12, 192(%rdi)
+ movq %r12, 64(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[11] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r8, 200(%rdi)
+ movq %r8, 72(%rdi)
movq %r14, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
@@ -4390,14 +4395,14 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r9, 208(%rdi)
- movq %r10, 216(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
movq 96(%rsi), %rdx
movq 96(%rbx), %r10
movq 104(%rbx), %r11
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
+ movq (%rdi), %r9
# A[12] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -4418,74 +4423,74 @@ _sp_2048_mul_avx2_16:
adcxq %rax, %r8
adoxq %rcx, %r9
movq %r8, 120(%rbx)
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
# A[12] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[12] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[12] * B[6]
mulx 48(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[12] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
- movq %r12, 152(%rdi)
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
- movq 192(%rdi), %r12
+ movq %r12, 24(%rdi)
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
# A[12] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[12] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[12] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[12] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
- movq %r11, 184(%rdi)
- movq 200(%rdi), %r8
- movq 208(%rdi), %r9
- movq 216(%rdi), %r10
+ movq %r11, 56(%rdi)
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
# A[12] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r12
adoxq %rcx, %r8
# A[12] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r12, 192(%rdi)
+ movq %r12, 64(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[12] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r8, 200(%rdi)
+ movq %r8, 72(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[12] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r9, 208(%rdi)
+ movq %r9, 80(%rdi)
movq %r14, %r11
adcxq %rax, %r10
adoxq %rcx, %r11
@@ -4493,14 +4498,14 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r10, 216(%rdi)
- movq %r11, 224(%rdi)
+ movq %r10, 88(%rdi)
+ movq %r11, 96(%rdi)
movq 104(%rsi), %rdx
movq 104(%rbx), %r11
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[13] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r11
@@ -4520,75 +4525,75 @@ _sp_2048_mul_avx2_16:
movq %r8, 120(%rbx)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[13] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[13] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[13] * B[6]
mulx 48(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[13] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 160(%rdi)
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
- movq 192(%rdi), %r12
- movq 200(%rdi), %r8
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
# A[13] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[13] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[13] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[13] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
- movq %r12, 192(%rdi)
- movq 208(%rdi), %r9
- movq 216(%rdi), %r10
- movq 224(%rdi), %r11
+ movq %r12, 64(%rdi)
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
+ movq 96(%rdi), %r11
# A[13] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[13] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r8, 200(%rdi)
+ movq %r8, 72(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[13] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r9, 208(%rdi)
+ movq %r9, 80(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[13] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r10, 216(%rdi)
+ movq %r10, 88(%rdi)
movq %r14, %r12
adcxq %rax, %r11
adoxq %rcx, %r12
@@ -4596,14 +4601,14 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r11, 224(%rdi)
- movq %r12, 232(%rdi)
+ movq %r11, 96(%rdi)
+ movq %r12, 104(%rdi)
movq 112(%rsi), %rdx
movq 112(%rbx), %r12
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
# A[14] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r12
@@ -4620,78 +4625,78 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[14] * B[3]
mulx 24(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
- movq %r10, 136(%rdi)
- movq 152(%rdi), %r12
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
# A[14] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r11
adoxq %rcx, %r12
# A[14] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r11, 144(%rdi)
+ movq %r11, 16(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[14] * B[6]
mulx 48(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[14] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 168(%rdi)
- movq 184(%rdi), %r11
- movq 192(%rdi), %r12
- movq 200(%rdi), %r8
- movq 208(%rdi), %r9
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
# A[14] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[14] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r10, 176(%rdi)
+ movq %r10, 48(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[14] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[14] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r12, 192(%rdi)
+ movq %r12, 64(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 200(%rdi)
- movq 216(%rdi), %r10
- movq 224(%rdi), %r11
- movq 232(%rdi), %r12
+ movq %r8, 72(%rdi)
+ movq 88(%rdi), %r10
+ movq 96(%rdi), %r11
+ movq 104(%rdi), %r12
# A[14] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[14] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r9, 208(%rdi)
+ movq %r9, 80(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[14] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r10, 216(%rdi)
+ movq %r10, 88(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[14] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r11, 224(%rdi)
+ movq %r11, 96(%rdi)
movq %r14, %r8
adcxq %rax, %r12
adoxq %rcx, %r8
@@ -4699,14 +4704,14 @@ _sp_2048_mul_avx2_16:
movq %r14, %r13
adoxq %r14, %r13
adcxq %r14, %r13
- movq %r12, 232(%rdi)
- movq %r8, 240(%rdi)
+ movq %r12, 104(%rdi)
+ movq %r8, 112(%rdi)
movq 120(%rsi), %rdx
movq 120(%rbx), %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
- movq 144(%rdi), %r11
- movq 152(%rdi), %r12
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
# A[15] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r8
@@ -4718,89 +4723,90 @@ _sp_2048_mul_avx2_16:
adoxq %rcx, %r10
# A[15] * B[2]
mulx 16(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
# A[15] * B[3]
mulx 24(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
- movq %r11, 144(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
- movq 176(%rdi), %r10
- movq 184(%rdi), %r11
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
# A[15] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r12
adoxq %rcx, %r8
# A[15] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r12, 152(%rdi)
+ movq %r12, 24(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[15] * B[6]
mulx 48(%rbp), %rax, %rcx
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
# A[15] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r9, 168(%rdi)
+ movq %r9, 40(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r11
- movq %r10, 176(%rdi)
- movq 192(%rdi), %r12
- movq 200(%rdi), %r8
- movq 208(%rdi), %r9
- movq 216(%rdi), %r10
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
# A[15] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r11
adoxq %rcx, %r12
# A[15] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r11, 184(%rdi)
+ movq %r11, 56(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[15] * B[10]
mulx 80(%rbp), %rax, %rcx
- movq %r12, 192(%rdi)
+ movq %r12, 64(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
# A[15] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 200(%rdi)
+ movq %r8, 72(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 208(%rdi)
- movq 224(%rdi), %r11
- movq 232(%rdi), %r12
- movq 240(%rdi), %r8
+ movq %r9, 80(%rdi)
+ movq 96(%rdi), %r11
+ movq 104(%rdi), %r12
+ movq 112(%rdi), %r8
# A[15] * B[12]
mulx 96(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r11
# A[15] * B[13]
mulx 104(%rbp), %rax, %rcx
- movq %r10, 216(%rdi)
+ movq %r10, 88(%rdi)
adcxq %rax, %r11
adoxq %rcx, %r12
# A[15] * B[14]
mulx 112(%rbp), %rax, %rcx
- movq %r11, 224(%rdi)
+ movq %r11, 96(%rdi)
adcxq %rax, %r12
adoxq %rcx, %r8
# A[15] * B[15]
mulx 120(%rbp), %rax, %rcx
- movq %r12, 232(%rdi)
+ movq %r12, 104(%rdi)
movq %r14, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
adcxq %r13, %r9
- movq %r8, 240(%rdi)
- movq %r9, 248(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ subq $0x80, %rdi
cmpq %rdi, %rsi
je L_start_2048_mul_avx2_16
cmpq %rdi, %rbp
@@ -4862,6 +4868,7 @@ _sp_2048_sqr_avx2_16:
cmpq %rdi, %rsi
movq %rsp, %rbp
cmovne %rdi, %rbp
+ addq $0x80, %rdi
xorq %r11, %r11
# Diagonal 1
xorq %r10, %r10
@@ -4957,7 +4964,7 @@ _sp_2048_sqr_avx2_16:
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 128(%rdi)
+ movq %r8, (%rdi)
# Diagonal 2
movq 24(%rbp), %r8
movq 32(%rbp), %r9
@@ -5033,7 +5040,7 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r9
+ movq (%rdi), %r9
movq %r11, %r10
# A[14] x A[1]
mulxq 112(%rsi), %rax, %rcx
@@ -5044,20 +5051,20 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r9
adoxq %rcx, %r10
# No store %rbx
- movq %r9, 128(%rdi)
+ movq %r9, (%rdi)
movq %r11, %r8
# A[15] x A[2]
movq 16(%rsi), %rdx
mulxq 120(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 136(%rdi)
+ movq %r10, 8(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 144(%rdi)
+ movq %r8, 16(%rdi)
# Diagonal 3
movq 40(%rbp), %r8
movq 48(%rbp), %r9
@@ -5120,8 +5127,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r10
- movq 136(%rdi), %r8
+ movq (%rdi), %r10
+ movq 8(%rdi), %r8
# A[13] x A[2]
mulxq 104(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -5131,8 +5138,8 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r10
adoxq %rcx, %r8
# No store %rbx
- movq %r10, 128(%rdi)
- movq 144(%rdi), %r9
+ movq %r10, (%rdi)
+ movq 16(%rdi), %r9
movq %r11, %r10
# A[14] x A[3]
movq 112(%rsi), %rdx
@@ -5143,20 +5150,20 @@ _sp_2048_sqr_avx2_16:
mulxq 32(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 136(%rdi)
- movq %r9, 144(%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
movq %r11, %r8
# A[14] x A[5]
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 152(%rdi)
+ movq %r10, 24(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 160(%rdi)
+ movq %r8, 32(%rdi)
# Diagonal 4
movq 56(%rbp), %r8
movq 64(%rbp), %r9
@@ -5208,8 +5215,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r8
- movq 136(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[12] x A[3]
mulxq 96(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -5219,9 +5226,9 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r8
adoxq %rcx, %r9
# No store %rbx
- movq %r8, 128(%rdi)
- movq 144(%rdi), %r10
- movq 152(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[13] x A[4]
movq 104(%rsi), %rdx
mulxq 32(%rsi), %rax, %rcx
@@ -5231,9 +5238,9 @@ _sp_2048_sqr_avx2_16:
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 136(%rdi)
- movq %r10, 144(%rdi)
- movq 160(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
movq %r11, %r10
# A[13] x A[6]
mulxq 48(%rsi), %rax, %rcx
@@ -5243,20 +5250,20 @@ _sp_2048_sqr_avx2_16:
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 152(%rdi)
- movq %r9, 160(%rdi)
+ movq %r8, 24(%rdi)
+ movq %r9, 32(%rdi)
movq %r11, %r8
# A[13] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 168(%rdi)
+ movq %r10, 40(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 176(%rdi)
+ movq %r8, 48(%rdi)
# Diagonal 5
movq 72(%rbp), %r8
movq 80(%rbp), %r9
@@ -5296,8 +5303,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[11] x A[4]
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -5307,9 +5314,9 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r9
adoxq %rcx, %r10
# No store %rbx
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
# A[12] x A[5]
movq 96(%rsi), %rdx
mulxq 40(%rsi), %rax, %rcx
@@ -5319,10 +5326,10 @@ _sp_2048_sqr_avx2_16:
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r10, 136(%rdi)
- movq %r8, 144(%rdi)
- movq 160(%rdi), %r10
- movq 168(%rdi), %r8
+ movq %r10, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r10
+ movq 40(%rdi), %r8
# A[12] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r9
@@ -5331,9 +5338,9 @@ _sp_2048_sqr_avx2_16:
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 152(%rdi)
- movq %r10, 160(%rdi)
- movq 176(%rdi), %r9
+ movq %r9, 24(%rdi)
+ movq %r10, 32(%rdi)
+ movq 48(%rdi), %r9
movq %r11, %r10
# A[12] x A[9]
mulxq 72(%rsi), %rax, %rcx
@@ -5343,20 +5350,20 @@ _sp_2048_sqr_avx2_16:
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 168(%rdi)
- movq %r9, 176(%rdi)
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
movq %r11, %r8
# A[12] x A[11]
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 184(%rdi)
+ movq %r10, 56(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 192(%rdi)
+ movq %r8, 64(%rdi)
# Diagonal 6
movq 88(%rbp), %r8
# No load %r13 - %r9
@@ -5384,8 +5391,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r10
- movq 136(%rdi), %r8
+ movq (%rdi), %r10
+ movq 8(%rdi), %r8
# A[10] x A[5]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -5395,9 +5402,9 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r10
adoxq %rcx, %r8
# No store %rbx
- movq %r10, 128(%rdi)
- movq 144(%rdi), %r9
- movq 152(%rdi), %r10
+ movq %r10, (%rdi)
+ movq 16(%rdi), %r9
+ movq 24(%rdi), %r10
# A[11] x A[6]
movq 88(%rsi), %rdx
mulxq 48(%rsi), %rax, %rcx
@@ -5407,10 +5414,10 @@ _sp_2048_sqr_avx2_16:
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 136(%rdi)
- movq %r9, 144(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[11] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r10
@@ -5419,10 +5426,10 @@ _sp_2048_sqr_avx2_16:
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r10, 152(%rdi)
- movq %r8, 160(%rdi)
- movq 176(%rdi), %r10
- movq 184(%rdi), %r8
+ movq %r10, 24(%rdi)
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r8
# A[11] x A[10]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r9
@@ -5432,9 +5439,9 @@ _sp_2048_sqr_avx2_16:
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 168(%rdi)
- movq %r10, 176(%rdi)
- movq 192(%rdi), %r9
+ movq %r9, 40(%rdi)
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r9
movq %r11, %r10
# A[13] x A[10]
mulxq 80(%rsi), %rax, %rcx
@@ -5444,20 +5451,20 @@ _sp_2048_sqr_avx2_16:
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 184(%rdi)
- movq %r9, 192(%rdi)
+ movq %r8, 56(%rdi)
+ movq %r9, 64(%rdi)
movq %r11, %r8
# A[13] x A[12]
mulxq 96(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 200(%rdi)
+ movq %r10, 72(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 208(%rdi)
+ movq %r8, 80(%rdi)
# Diagonal 7
# No load %r14 - %r8
# No load %r15 - %r9
@@ -5473,8 +5480,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rcx, %rbx
# No store %r14
# No store %r15
- movq 128(%rdi), %r8
- movq 136(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[9] x A[6]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -5484,9 +5491,9 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r8
adoxq %rcx, %r9
# No store %rbx
- movq %r8, 128(%rdi)
- movq 144(%rdi), %r10
- movq 152(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[10] x A[7]
movq 80(%rsi), %rdx
mulxq 56(%rsi), %rax, %rcx
@@ -5496,10 +5503,10 @@ _sp_2048_sqr_avx2_16:
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 136(%rdi)
- movq %r10, 144(%rdi)
- movq 160(%rdi), %r9
- movq 168(%rdi), %r10
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq 40(%rdi), %r10
# A[10] x A[9]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
@@ -5509,10 +5516,10 @@ _sp_2048_sqr_avx2_16:
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 152(%rdi)
- movq %r9, 160(%rdi)
- movq 176(%rdi), %r8
- movq 184(%rdi), %r9
+ movq %r8, 24(%rdi)
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
# A[14] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r10
@@ -5521,10 +5528,10 @@ _sp_2048_sqr_avx2_16:
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r10, 168(%rdi)
- movq %r8, 176(%rdi)
- movq 192(%rdi), %r10
- movq 200(%rdi), %r8
+ movq %r10, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r10
+ movq 72(%rdi), %r8
# A[14] x A[9]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r9
@@ -5533,9 +5540,9 @@ _sp_2048_sqr_avx2_16:
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 184(%rdi)
- movq %r10, 192(%rdi)
- movq 208(%rdi), %r9
+ movq %r9, 56(%rdi)
+ movq %r10, 64(%rdi)
+ movq 80(%rdi), %r9
movq %r11, %r10
# A[14] x A[11]
mulxq 88(%rsi), %rax, %rcx
@@ -5545,24 +5552,24 @@ _sp_2048_sqr_avx2_16:
mulxq 96(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 200(%rdi)
- movq %r9, 208(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
movq %r11, %r8
# A[14] x A[13]
mulxq 104(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 216(%rdi)
+ movq %r10, 88(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 224(%rdi)
+ movq %r8, 96(%rdi)
# Diagonal 8
# No load %rbx - %r8
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
# A[8] x A[7]
movq 56(%rsi), %rdx
mulxq 64(%rsi), %rax, %rcx
@@ -5573,9 +5580,9 @@ _sp_2048_sqr_avx2_16:
adcxq %rax, %r9
adoxq %rcx, %r10
# No store %rbx
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
# A[9] x A[8]
movq 64(%rsi), %rdx
mulxq 72(%rsi), %rax, %rcx
@@ -5586,10 +5593,10 @@ _sp_2048_sqr_avx2_16:
mulxq 24(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r10, 136(%rdi)
- movq %r8, 144(%rdi)
- movq 160(%rdi), %r10
- movq 168(%rdi), %r8
+ movq %r10, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r10
+ movq 40(%rdi), %r8
# A[15] x A[4]
mulxq 32(%rsi), %rax, %rcx
adcxq %rax, %r9
@@ -5598,10 +5605,10 @@ _sp_2048_sqr_avx2_16:
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 152(%rdi)
- movq %r10, 160(%rdi)
- movq 176(%rdi), %r9
- movq 184(%rdi), %r10
+ movq %r9, 24(%rdi)
+ movq %r10, 32(%rdi)
+ movq 48(%rdi), %r9
+ movq 56(%rdi), %r10
# A[15] x A[6]
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r8
@@ -5610,10 +5617,10 @@ _sp_2048_sqr_avx2_16:
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 168(%rdi)
- movq %r9, 176(%rdi)
- movq 192(%rdi), %r8
- movq 200(%rdi), %r9
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
# A[15] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r10
@@ -5622,10 +5629,10 @@ _sp_2048_sqr_avx2_16:
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r10, 184(%rdi)
- movq %r8, 192(%rdi)
- movq 208(%rdi), %r10
- movq 216(%rdi), %r8
+ movq %r10, 56(%rdi)
+ movq %r8, 64(%rdi)
+ movq 80(%rdi), %r10
+ movq 88(%rdi), %r8
# A[15] x A[10]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r9
@@ -5634,9 +5641,9 @@ _sp_2048_sqr_avx2_16:
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r9, 200(%rdi)
- movq %r10, 208(%rdi)
- movq 224(%rdi), %r9
+ movq %r9, 72(%rdi)
+ movq %r10, 80(%rdi)
+ movq 96(%rdi), %r9
movq %r11, %r10
# A[15] x A[12]
mulxq 96(%rsi), %rax, %rcx
@@ -5646,21 +5653,21 @@ _sp_2048_sqr_avx2_16:
mulxq 104(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r8, 216(%rdi)
- movq %r9, 224(%rdi)
+ movq %r8, 88(%rdi)
+ movq %r9, 96(%rdi)
movq %r11, %r8
# A[15] x A[14]
mulxq 112(%rsi), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 232(%rdi)
+ movq %r10, 104(%rdi)
# Carry
adcxq %r12, %r8
movq %r11, %r12
adcxq %r11, %r12
adoxq %r11, %r12
- movq %r8, 240(%rdi)
- movq %r12, 248(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r12, 120(%rdi)
# Double and Add in A[i] x A[i]
movq 8(%rbp), %r9
# A[0] x A[0]
@@ -5739,8 +5746,8 @@ _sp_2048_sqr_avx2_16:
adoxq %rbx, %rbx
adcxq %rax, %r15
adcxq %rcx, %rbx
- movq 128(%rdi), %r8
- movq 136(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[8] x A[8]
movq 64(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5748,10 +5755,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 128(%rdi)
- movq %r9, 136(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
# A[9] x A[9]
movq 72(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5759,10 +5766,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 144(%rdi)
- movq %r9, 152(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[10] x A[10]
movq 80(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5770,10 +5777,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 160(%rdi)
- movq %r9, 168(%rdi)
- movq 176(%rdi), %r8
- movq 184(%rdi), %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
# A[11] x A[11]
movq 88(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5781,10 +5788,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 176(%rdi)
- movq %r9, 184(%rdi)
- movq 192(%rdi), %r8
- movq 200(%rdi), %r9
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
# A[12] x A[12]
movq 96(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5792,10 +5799,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 192(%rdi)
- movq %r9, 200(%rdi)
- movq 208(%rdi), %r8
- movq 216(%rdi), %r9
+ movq %r8, 64(%rdi)
+ movq %r9, 72(%rdi)
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
# A[13] x A[13]
movq 104(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5803,10 +5810,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 208(%rdi)
- movq %r9, 216(%rdi)
- movq 224(%rdi), %r8
- movq 232(%rdi), %r9
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rdi), %r8
+ movq 104(%rdi), %r9
# A[14] x A[14]
movq 112(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5814,10 +5821,10 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 224(%rdi)
- movq %r9, 232(%rdi)
- movq 240(%rdi), %r8
- movq 248(%rdi), %r9
+ movq %r8, 96(%rdi)
+ movq %r9, 104(%rdi)
+ movq 112(%rdi), %r8
+ movq 120(%rdi), %r9
# A[15] x A[15]
movq 120(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -5825,12 +5832,13 @@ _sp_2048_sqr_avx2_16:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 240(%rdi)
- movq %r9, 248(%rdi)
- movq %r13, 96(%rdi)
- movq %r14, 104(%rdi)
- movq %r15, 112(%rdi)
- movq %rbx, 120(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ movq %r13, -32(%rdi)
+ movq %r14, -24(%rdi)
+ movq %r15, -16(%rdi)
+ movq %rbx, -8(%rdi)
+ subq $0x80, %rdi
cmpq %rdi, %rsi
jne L_end_2048_sqr_avx2_16
vmovdqu (%rbp), %xmm0
@@ -6331,6 +6339,11 @@ _sp_2048_mul_32:
#else
callq _sp_2048_mul_16
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 784(%rsp), %rdx
+ movq 776(%rsp), %rsi
+ movq 768(%rsp), %rdi
+#endif /* _WIN64 */
movq 792(%rsp), %r13
movq 800(%rsp), %r14
movq 768(%rsp), %r15
@@ -7059,6 +7072,10 @@ _sp_2048_sqr_32:
#else
callq _sp_2048_sqr_16
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 648(%rsp), %rsi
+ movq 640(%rsp), %rdi
+#endif /* _WIN64 */
movq 656(%rsp), %r10
leaq 512(%rsp), %r8
movq %r10, %rcx
@@ -7560,6 +7577,7 @@ _sp_2048_sqr_32:
#ifndef __APPLE__
.size sp_2048_sqr_32,.-sp_2048_sqr_32
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -7720,6 +7738,11 @@ _sp_2048_mul_avx2_32:
#else
callq _sp_2048_mul_avx2_16
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 784(%rsp), %rdx
+ movq 776(%rsp), %rsi
+ movq 768(%rsp), %rdi
+#endif /* _WIN64 */
movq 792(%rsp), %r13
movq 800(%rsp), %r14
movq 768(%rsp), %r15
@@ -8233,6 +8256,8 @@ _sp_2048_mul_avx2_32:
#ifndef __APPLE__
.size sp_2048_mul_avx2_32,.-sp_2048_mul_avx2_32
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square a and put result in r. (r = a * a)
*
* r A single precision integer.
@@ -8329,6 +8354,10 @@ _sp_2048_sqr_avx2_32:
#else
callq _sp_2048_sqr_avx2_16
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 648(%rsp), %rsi
+ movq 640(%rsp), %rdi
+#endif /* _WIN64 */
movq 656(%rsp), %r10
leaq 512(%rsp), %r8
movq %r10, %rcx
@@ -8798,6 +8827,78 @@ _sp_2048_sqr_avx2_32:
#ifndef __APPLE__
.size sp_2048_sqr_avx2_32,.-sp_2048_sqr_avx2_32
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer and result.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_2048_sub_in_place_16
+.type sp_2048_sub_in_place_16,@function
+.align 16
+sp_2048_sub_in_place_16:
+#else
+.section __TEXT,__text
+.globl _sp_2048_sub_in_place_16
+.p2align 4
+_sp_2048_sub_in_place_16:
+#endif /* __APPLE__ */
+ movq (%rdi), %rdx
+ xorq %rax, %rax
+ subq (%rsi), %rdx
+ movq 8(%rdi), %rcx
+ movq %rdx, (%rdi)
+ sbbq 8(%rsi), %rcx
+ movq 16(%rdi), %rdx
+ movq %rcx, 8(%rdi)
+ sbbq 16(%rsi), %rdx
+ movq 24(%rdi), %rcx
+ movq %rdx, 16(%rdi)
+ sbbq 24(%rsi), %rcx
+ movq 32(%rdi), %rdx
+ movq %rcx, 24(%rdi)
+ sbbq 32(%rsi), %rdx
+ movq 40(%rdi), %rcx
+ movq %rdx, 32(%rdi)
+ sbbq 40(%rsi), %rcx
+ movq 48(%rdi), %rdx
+ movq %rcx, 40(%rdi)
+ sbbq 48(%rsi), %rdx
+ movq 56(%rdi), %rcx
+ movq %rdx, 48(%rdi)
+ sbbq 56(%rsi), %rcx
+ movq 64(%rdi), %rdx
+ movq %rcx, 56(%rdi)
+ sbbq 64(%rsi), %rdx
+ movq 72(%rdi), %rcx
+ movq %rdx, 64(%rdi)
+ sbbq 72(%rsi), %rcx
+ movq 80(%rdi), %rdx
+ movq %rcx, 72(%rdi)
+ sbbq 80(%rsi), %rdx
+ movq 88(%rdi), %rcx
+ movq %rdx, 80(%rdi)
+ sbbq 88(%rsi), %rcx
+ movq 96(%rdi), %rdx
+ movq %rcx, 88(%rdi)
+ sbbq 96(%rsi), %rdx
+ movq 104(%rdi), %rcx
+ movq %rdx, 96(%rdi)
+ sbbq 104(%rsi), %rcx
+ movq 112(%rdi), %rdx
+ movq %rcx, 104(%rdi)
+ sbbq 112(%rsi), %rdx
+ movq 120(%rdi), %rcx
+ movq %rdx, 112(%rdi)
+ sbbq 120(%rsi), %rcx
+ movq %rcx, 120(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16
+#endif /* __APPLE__ */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -9075,77 +9176,6 @@ _sp_2048_mul_d_32:
#ifndef __APPLE__
.size sp_2048_mul_d_32,.-sp_2048_mul_d_32
#endif /* __APPLE__ */
-/* Sub b from a into a. (a -= b)
- *
- * a A single precision integer and result.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_2048_sub_in_place_16
-.type sp_2048_sub_in_place_16,@function
-.align 16
-sp_2048_sub_in_place_16:
-#else
-.section __TEXT,__text
-.globl _sp_2048_sub_in_place_16
-.p2align 4
-_sp_2048_sub_in_place_16:
-#endif /* __APPLE__ */
- movq (%rdi), %rdx
- xorq %rax, %rax
- subq (%rsi), %rdx
- movq 8(%rdi), %rcx
- movq %rdx, (%rdi)
- sbbq 8(%rsi), %rcx
- movq 16(%rdi), %rdx
- movq %rcx, 8(%rdi)
- sbbq 16(%rsi), %rdx
- movq 24(%rdi), %rcx
- movq %rdx, 16(%rdi)
- sbbq 24(%rsi), %rcx
- movq 32(%rdi), %rdx
- movq %rcx, 24(%rdi)
- sbbq 32(%rsi), %rdx
- movq 40(%rdi), %rcx
- movq %rdx, 32(%rdi)
- sbbq 40(%rsi), %rcx
- movq 48(%rdi), %rdx
- movq %rcx, 40(%rdi)
- sbbq 48(%rsi), %rdx
- movq 56(%rdi), %rcx
- movq %rdx, 48(%rdi)
- sbbq 56(%rsi), %rcx
- movq 64(%rdi), %rdx
- movq %rcx, 56(%rdi)
- sbbq 64(%rsi), %rdx
- movq 72(%rdi), %rcx
- movq %rdx, 64(%rdi)
- sbbq 72(%rsi), %rcx
- movq 80(%rdi), %rdx
- movq %rcx, 72(%rdi)
- sbbq 80(%rsi), %rdx
- movq 88(%rdi), %rcx
- movq %rdx, 80(%rdi)
- sbbq 88(%rsi), %rcx
- movq 96(%rdi), %rdx
- movq %rcx, 88(%rdi)
- sbbq 96(%rsi), %rdx
- movq 104(%rdi), %rcx
- movq %rdx, 96(%rdi)
- sbbq 104(%rsi), %rcx
- movq 112(%rdi), %rdx
- movq %rcx, 104(%rdi)
- sbbq 112(%rsi), %rdx
- movq 120(%rdi), %rcx
- movq %rdx, 112(%rdi)
- sbbq 120(%rsi), %rcx
- movq %rcx, 120(%rdi)
- sbbq $0x00, %rax
- repz retq
-#ifndef __APPLE__
-.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16
-#endif /* __APPLE__ */
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -9314,7 +9344,7 @@ _sp_2048_mont_reduce_16:
movq $16, %r8
movq (%rdi), %r13
movq 8(%rdi), %r14
-L_mont_loop_16:
+L_2048_mont_loop_16:
# mu = a[i] * mp
movq %r13, %r11
imulq %rcx, %r11
@@ -9477,12 +9507,17 @@ L_mont_loop_16:
# i -= 1
addq $8, %rdi
decq %r8
- jnz L_mont_loop_16
+ jnz L_2048_mont_loop_16
movq %r13, (%rdi)
movq %r14, 8(%rdi)
negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
movq %r15, %rcx
movq %rsi, %rdx
+#endif /* _WIN64 */
movq %rdi, %rsi
movq %rdi, %rdi
subq $0x80, %rdi
@@ -9499,6 +9534,7 @@ L_mont_loop_16:
#ifndef __APPLE__
.size sp_2048_mont_reduce_16,.-sp_2048_mont_reduce_16
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -9605,6 +9641,7 @@ _sp_2048_cond_sub_avx2_16:
#ifndef __APPLE__
.size sp_2048_cond_sub_avx2_16,.-sp_2048_cond_sub_avx2_16
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -9783,86 +9820,86 @@ _sp_2048_mul_d_avx2_16:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 40(%rdi)
adoxq %r8, %r9
+ movq %r10, 40(%rdi)
# A[6] * B
mulxq 48(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 48(%rdi)
adoxq %r8, %r10
+ movq %r9, 48(%rdi)
# A[7] * B
mulxq 56(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 56(%rdi)
adoxq %r8, %r9
+ movq %r10, 56(%rdi)
# A[8] * B
mulxq 64(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 64(%rdi)
adoxq %r8, %r10
+ movq %r9, 64(%rdi)
# A[9] * B
mulxq 72(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 72(%rdi)
adoxq %r8, %r9
+ movq %r10, 72(%rdi)
# A[10] * B
mulxq 80(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 80(%rdi)
adoxq %r8, %r10
+ movq %r9, 80(%rdi)
# A[11] * B
mulxq 88(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 88(%rdi)
adoxq %r8, %r9
+ movq %r10, 88(%rdi)
# A[12] * B
mulxq 96(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 96(%rdi)
adoxq %r8, %r10
+ movq %r9, 96(%rdi)
# A[13] * B
mulxq 104(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 104(%rdi)
adoxq %r8, %r9
+ movq %r10, 104(%rdi)
# A[14] * B
mulxq 112(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 112(%rdi)
adoxq %r8, %r10
+ movq %r9, 112(%rdi)
# A[15] * B
mulxq 120(%rsi), %rcx, %r8
movq %r11, %r9
@@ -9876,6 +9913,35 @@ _sp_2048_mul_d_avx2_16:
.size sp_2048_mul_d_avx2_16,.-sp_2048_mul_d_avx2_16
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_2048_word_asm_16
+.type div_2048_word_asm_16,@function
+.align 16
+div_2048_word_asm_16:
+#else
+.section __TEXT,__text
+.globl _div_2048_word_asm_16
+.p2align 4
+_div_2048_word_asm_16:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_2048_word_asm_16,.-div_2048_word_asm_16
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -10054,14 +10120,20 @@ _sp_2048_mont_reduce_avx2_16:
pushq %r12
pushq %r13
pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
movq %rdx, %r8
- xorq %r14, %r14
+ xorq %rbp, %rbp
# i = 16
movq $16, %r9
movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
addq $0x40, %rdi
- xorq %r12, %r12
-L_mont_loop_avx2_16:
+ xorq %rbp, %rbp
+L_2048_mont_loop_avx2_16:
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -10069,32 +10141,29 @@ L_mont_loop_avx2_16:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -56(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -48(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -40(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -48(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -32(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -40(%rdi)
+ movq -32(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -24(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -32(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -16(%rdi), %r10
@@ -10161,11 +10230,11 @@ L_mont_loop_avx2_16:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 56(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 64(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -10173,32 +10242,29 @@ L_mont_loop_avx2_16:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -48(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -40(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -32(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -40(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -24(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -32(%rdi)
+ movq -24(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -16(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -24(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -8(%rdi), %r10
@@ -10265,100 +10331,103 @@ L_mont_loop_avx2_16:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 64(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 72(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# a += 2
addq $16, %rdi
# i -= 2
subq $2, %r9
- jnz L_mont_loop_avx2_16
+ jnz L_2048_mont_loop_avx2_16
subq $0x40, %rdi
- negq %r14
+ negq %rbp
movq %rdi, %r8
subq $0x80, %rdi
movq (%rsi), %rcx
movq %r13, %rdx
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
subq %rcx, %rdx
movq 8(%rsi), %rcx
- movq 8(%r8), %rax
- pextq %r14, %rcx, %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
movq %rdx, (%rdi)
sbbq %rcx, %rax
movq 16(%rsi), %rdx
- movq 16(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
movq %rax, 8(%rdi)
sbbq %rdx, %rcx
movq 24(%rsi), %rax
- movq 24(%r8), %rdx
- pextq %r14, %rax, %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
movq %rcx, 16(%rdi)
sbbq %rax, %rdx
movq 32(%rsi), %rcx
movq 32(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 24(%rdi)
sbbq %rcx, %rax
movq 40(%rsi), %rdx
movq 40(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 32(%rdi)
sbbq %rdx, %rcx
movq 48(%rsi), %rax
movq 48(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 40(%rdi)
sbbq %rax, %rdx
movq 56(%rsi), %rcx
movq 56(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 48(%rdi)
sbbq %rcx, %rax
movq 64(%rsi), %rdx
movq 64(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 56(%rdi)
sbbq %rdx, %rcx
movq 72(%rsi), %rax
movq 72(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 64(%rdi)
sbbq %rax, %rdx
movq 80(%rsi), %rcx
movq 80(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 72(%rdi)
sbbq %rcx, %rax
movq 88(%rsi), %rdx
movq 88(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 80(%rdi)
sbbq %rdx, %rcx
movq 96(%rsi), %rax
movq 96(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 88(%rdi)
sbbq %rax, %rdx
movq 104(%rsi), %rcx
movq 104(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 96(%rdi)
sbbq %rcx, %rax
movq 112(%rsi), %rdx
movq 112(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 104(%rdi)
sbbq %rdx, %rcx
movq 120(%rsi), %rax
movq 120(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 112(%rdi)
sbbq %rax, %rdx
movq %rdx, 120(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
popq %r14
popq %r13
popq %r12
@@ -10647,7 +10716,7 @@ _sp_2048_mont_reduce_32:
movq $32, %r8
movq (%rdi), %r13
movq 8(%rdi), %r14
-L_mont_loop_32:
+L_2048_mont_loop_32:
# mu = a[i] * mp
movq %r13, %r11
imulq %rcx, %r11
@@ -10970,12 +11039,17 @@ L_mont_loop_32:
# i -= 1
addq $8, %rdi
decq %r8
- jnz L_mont_loop_32
+ jnz L_2048_mont_loop_32
movq %r13, (%rdi)
movq %r14, 8(%rdi)
negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
movq %r15, %rcx
movq %rsi, %rdx
+#endif /* _WIN64 */
movq %rdi, %rsi
movq %rdi, %rdi
subq $0x100, %rdi
@@ -10992,6 +11066,7 @@ L_mont_loop_32:
#ifndef __APPLE__
.size sp_2048_mont_reduce_32,.-sp_2048_mont_reduce_32
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -11178,6 +11253,7 @@ _sp_2048_cond_sub_avx2_32:
#ifndef __APPLE__
.size sp_2048_cond_sub_avx2_32,.-sp_2048_cond_sub_avx2_32
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifdef HAVE_INTEL_AVX2
/* Mul a by digit b into r. (r = a * b)
*
@@ -11207,182 +11283,182 @@ _sp_2048_mul_d_avx2_32:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 40(%rdi)
adoxq %r8, %r9
+ movq %r10, 40(%rdi)
# A[6] * B
mulxq 48(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 48(%rdi)
adoxq %r8, %r10
+ movq %r9, 48(%rdi)
# A[7] * B
mulxq 56(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 56(%rdi)
adoxq %r8, %r9
+ movq %r10, 56(%rdi)
# A[8] * B
mulxq 64(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 64(%rdi)
adoxq %r8, %r10
+ movq %r9, 64(%rdi)
# A[9] * B
mulxq 72(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 72(%rdi)
adoxq %r8, %r9
+ movq %r10, 72(%rdi)
# A[10] * B
mulxq 80(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 80(%rdi)
adoxq %r8, %r10
+ movq %r9, 80(%rdi)
# A[11] * B
mulxq 88(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 88(%rdi)
adoxq %r8, %r9
+ movq %r10, 88(%rdi)
# A[12] * B
mulxq 96(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 96(%rdi)
adoxq %r8, %r10
+ movq %r9, 96(%rdi)
# A[13] * B
mulxq 104(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 104(%rdi)
adoxq %r8, %r9
+ movq %r10, 104(%rdi)
# A[14] * B
mulxq 112(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 112(%rdi)
adoxq %r8, %r10
+ movq %r9, 112(%rdi)
# A[15] * B
mulxq 120(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 120(%rdi)
adoxq %r8, %r9
+ movq %r10, 120(%rdi)
# A[16] * B
mulxq 128(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 128(%rdi)
adoxq %r8, %r10
+ movq %r9, 128(%rdi)
# A[17] * B
mulxq 136(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 136(%rdi)
adoxq %r8, %r9
+ movq %r10, 136(%rdi)
# A[18] * B
mulxq 144(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 144(%rdi)
adoxq %r8, %r10
+ movq %r9, 144(%rdi)
# A[19] * B
mulxq 152(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 152(%rdi)
adoxq %r8, %r9
+ movq %r10, 152(%rdi)
# A[20] * B
mulxq 160(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 160(%rdi)
adoxq %r8, %r10
+ movq %r9, 160(%rdi)
# A[21] * B
mulxq 168(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 168(%rdi)
adoxq %r8, %r9
+ movq %r10, 168(%rdi)
# A[22] * B
mulxq 176(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 176(%rdi)
adoxq %r8, %r10
+ movq %r9, 176(%rdi)
# A[23] * B
mulxq 184(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 184(%rdi)
adoxq %r8, %r9
+ movq %r10, 184(%rdi)
# A[24] * B
mulxq 192(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 192(%rdi)
adoxq %r8, %r10
+ movq %r9, 192(%rdi)
# A[25] * B
mulxq 200(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 200(%rdi)
adoxq %r8, %r9
+ movq %r10, 200(%rdi)
# A[26] * B
mulxq 208(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 208(%rdi)
adoxq %r8, %r10
+ movq %r9, 208(%rdi)
# A[27] * B
mulxq 216(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 216(%rdi)
adoxq %r8, %r9
+ movq %r10, 216(%rdi)
# A[28] * B
mulxq 224(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 224(%rdi)
adoxq %r8, %r10
+ movq %r9, 224(%rdi)
# A[29] * B
mulxq 232(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 232(%rdi)
adoxq %r8, %r9
+ movq %r10, 232(%rdi)
# A[30] * B
mulxq 240(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 240(%rdi)
adoxq %r8, %r10
+ movq %r9, 240(%rdi)
# A[31] * B
mulxq 248(%rsi), %rcx, %r8
movq %r11, %r9
@@ -11396,6 +11472,35 @@ _sp_2048_mul_d_avx2_32:
.size sp_2048_mul_d_avx2_32,.-sp_2048_mul_d_avx2_32
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_2048_word_asm_32
+.type div_2048_word_asm_32,@function
+.align 16
+div_2048_word_asm_32:
+#else
+.section __TEXT,__text
+.globl _div_2048_word_asm_32
+.p2align 4
+_div_2048_word_asm_32:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_2048_word_asm_32,.-div_2048_word_asm_32
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -11822,14 +11927,20 @@ _sp_2048_mont_reduce_avx2_32:
pushq %r12
pushq %r13
pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
movq %rdx, %r8
- xorq %r14, %r14
+ xorq %rbp, %rbp
# i = 32
movq $32, %r9
movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
addq $0x80, %rdi
- xorq %r12, %r12
-L_mont_loop_avx2_32:
+ xorq %rbp, %rbp
+L_2048_mont_loop_avx2_32:
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -11837,32 +11948,29 @@ L_mont_loop_avx2_32:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -120(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -112(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -104(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -112(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -96(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -104(%rdi)
+ movq -96(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -88(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -96(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -80(%rdi), %r10
@@ -12025,180 +12133,183 @@ L_mont_loop_avx2_32:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 120(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 128(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# a += 1
addq $8, %rdi
# i -= 1
subq $0x01, %r9
- jnz L_mont_loop_avx2_32
+ jnz L_2048_mont_loop_avx2_32
subq $0x80, %rdi
- negq %r14
+ negq %rbp
movq %rdi, %r8
subq $0x100, %rdi
movq (%rsi), %rcx
movq %r13, %rdx
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
subq %rcx, %rdx
movq 8(%rsi), %rcx
- movq 8(%r8), %rax
- pextq %r14, %rcx, %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
movq %rdx, (%rdi)
sbbq %rcx, %rax
movq 16(%rsi), %rdx
- movq 16(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
movq %rax, 8(%rdi)
sbbq %rdx, %rcx
movq 24(%rsi), %rax
- movq 24(%r8), %rdx
- pextq %r14, %rax, %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
movq %rcx, 16(%rdi)
sbbq %rax, %rdx
movq 32(%rsi), %rcx
movq 32(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 24(%rdi)
sbbq %rcx, %rax
movq 40(%rsi), %rdx
movq 40(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 32(%rdi)
sbbq %rdx, %rcx
movq 48(%rsi), %rax
movq 48(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 40(%rdi)
sbbq %rax, %rdx
movq 56(%rsi), %rcx
movq 56(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 48(%rdi)
sbbq %rcx, %rax
movq 64(%rsi), %rdx
movq 64(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 56(%rdi)
sbbq %rdx, %rcx
movq 72(%rsi), %rax
movq 72(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 64(%rdi)
sbbq %rax, %rdx
movq 80(%rsi), %rcx
movq 80(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 72(%rdi)
sbbq %rcx, %rax
movq 88(%rsi), %rdx
movq 88(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 80(%rdi)
sbbq %rdx, %rcx
movq 96(%rsi), %rax
movq 96(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 88(%rdi)
sbbq %rax, %rdx
movq 104(%rsi), %rcx
movq 104(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 96(%rdi)
sbbq %rcx, %rax
movq 112(%rsi), %rdx
movq 112(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 104(%rdi)
sbbq %rdx, %rcx
movq 120(%rsi), %rax
movq 120(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 112(%rdi)
sbbq %rax, %rdx
movq 128(%rsi), %rcx
movq 128(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 120(%rdi)
sbbq %rcx, %rax
movq 136(%rsi), %rdx
movq 136(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 128(%rdi)
sbbq %rdx, %rcx
movq 144(%rsi), %rax
movq 144(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 136(%rdi)
sbbq %rax, %rdx
movq 152(%rsi), %rcx
movq 152(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 144(%rdi)
sbbq %rcx, %rax
movq 160(%rsi), %rdx
movq 160(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 152(%rdi)
sbbq %rdx, %rcx
movq 168(%rsi), %rax
movq 168(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 160(%rdi)
sbbq %rax, %rdx
movq 176(%rsi), %rcx
movq 176(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 168(%rdi)
sbbq %rcx, %rax
movq 184(%rsi), %rdx
movq 184(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 176(%rdi)
sbbq %rdx, %rcx
movq 192(%rsi), %rax
movq 192(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 184(%rdi)
sbbq %rax, %rdx
movq 200(%rsi), %rcx
movq 200(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 192(%rdi)
sbbq %rcx, %rax
movq 208(%rsi), %rdx
movq 208(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 200(%rdi)
sbbq %rdx, %rcx
movq 216(%rsi), %rax
movq 216(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 208(%rdi)
sbbq %rax, %rdx
movq 224(%rsi), %rcx
movq 224(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 216(%rdi)
sbbq %rcx, %rax
movq 232(%rsi), %rdx
movq 232(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 224(%rdi)
sbbq %rdx, %rcx
movq 240(%rsi), %rax
movq 240(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 232(%rdi)
sbbq %rax, %rdx
movq 248(%rsi), %rcx
movq 248(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 240(%rdi)
sbbq %rcx, %rax
movq %rax, 248(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
popq %r14
popq %r13
popq %r12
@@ -12347,6 +12458,7 @@ _sp_2048_cond_add_16:
#ifndef __APPLE__
.size sp_2048_cond_add_16,.-sp_2048_cond_add_16
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -12453,6 +12565,7 @@ _sp_2048_cond_add_avx2_16:
#ifndef __APPLE__
.size sp_2048_cond_add_avx2_16,.-sp_2048_cond_add_avx2_16
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Shift number left by n bit. (r = a << n)
*
* r Result of left shift by n.
@@ -12471,107 +12584,116 @@ sp_2048_lshift_32:
.p2align 4
_sp_2048_lshift_32:
#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ movq %rdi, %r9
movb %dl, %cl
- movq $0x00, %r10
- movq 216(%rsi), %r11
- movq 224(%rsi), %rdx
- movq 232(%rsi), %rax
- movq 240(%rsi), %r8
- movq 248(%rsi), %r9
- shldq %cl, %r9, %r10
- shldq %cl, %r8, %r9
+ movq %rsi, %rdx
+ movq $0x00, %r12
+ movq 216(%rdx), %r13
+ movq 224(%rdx), %rax
+ movq 232(%rdx), %r8
+ movq 240(%rdx), %r10
+ movq 248(%rdx), %r11
+ shldq %cl, %r11, %r12
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 224(%rdi)
- movq %rax, 232(%rdi)
- movq %r8, 240(%rdi)
- movq %r9, 248(%rdi)
- movq %r10, 256(%rdi)
- movq 184(%rsi), %r9
- movq 192(%rsi), %rdx
- movq 200(%rsi), %rax
- movq 208(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 224(%r9)
+ movq %r8, 232(%r9)
+ movq %r10, 240(%r9)
+ movq %r11, 248(%r9)
+ movq %r12, 256(%r9)
+ movq 184(%rdx), %r11
+ movq 192(%rdx), %rax
+ movq 200(%rdx), %r8
+ movq 208(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 192(%rdi)
- movq %rax, 200(%rdi)
- movq %r8, 208(%rdi)
- movq %r11, 216(%rdi)
- movq 152(%rsi), %r11
- movq 160(%rsi), %rdx
- movq 168(%rsi), %rax
- movq 176(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 192(%r9)
+ movq %r8, 200(%r9)
+ movq %r10, 208(%r9)
+ movq %r13, 216(%r9)
+ movq 152(%rdx), %r13
+ movq 160(%rdx), %rax
+ movq 168(%rdx), %r8
+ movq 176(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 160(%rdi)
- movq %rax, 168(%rdi)
- movq %r8, 176(%rdi)
- movq %r9, 184(%rdi)
- movq 120(%rsi), %r9
- movq 128(%rsi), %rdx
- movq 136(%rsi), %rax
- movq 144(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 160(%r9)
+ movq %r8, 168(%r9)
+ movq %r10, 176(%r9)
+ movq %r11, 184(%r9)
+ movq 120(%rdx), %r11
+ movq 128(%rdx), %rax
+ movq 136(%rdx), %r8
+ movq 144(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 128(%rdi)
- movq %rax, 136(%rdi)
- movq %r8, 144(%rdi)
- movq %r11, 152(%rdi)
- movq 88(%rsi), %r11
- movq 96(%rsi), %rdx
- movq 104(%rsi), %rax
- movq 112(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 128(%r9)
+ movq %r8, 136(%r9)
+ movq %r10, 144(%r9)
+ movq %r13, 152(%r9)
+ movq 88(%rdx), %r13
+ movq 96(%rdx), %rax
+ movq 104(%rdx), %r8
+ movq 112(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 96(%rdi)
- movq %rax, 104(%rdi)
- movq %r8, 112(%rdi)
- movq %r9, 120(%rdi)
- movq 56(%rsi), %r9
- movq 64(%rsi), %rdx
- movq 72(%rsi), %rax
- movq 80(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 96(%r9)
+ movq %r8, 104(%r9)
+ movq %r10, 112(%r9)
+ movq %r11, 120(%r9)
+ movq 56(%rdx), %r11
+ movq 64(%rdx), %rax
+ movq 72(%rdx), %r8
+ movq 80(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 64(%rdi)
- movq %rax, 72(%rdi)
- movq %r8, 80(%rdi)
- movq %r11, 88(%rdi)
- movq 24(%rsi), %r11
- movq 32(%rsi), %rdx
- movq 40(%rsi), %rax
- movq 48(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 64(%r9)
+ movq %r8, 72(%r9)
+ movq %r10, 80(%r9)
+ movq %r13, 88(%r9)
+ movq 24(%rdx), %r13
+ movq 32(%rdx), %rax
+ movq 40(%rdx), %r8
+ movq 48(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 32(%rdi)
- movq %rax, 40(%rdi)
- movq %r8, 48(%rdi)
- movq %r9, 56(%rdi)
- movq (%rsi), %rdx
- movq 8(%rsi), %rax
- movq 16(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 32(%r9)
+ movq %r8, 40(%r9)
+ movq %r10, 48(%r9)
+ movq %r11, 56(%r9)
+ movq (%rdx), %rax
+ movq 8(%rdx), %r8
+ movq 16(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shlq %cl, %rdx
- movq %rdx, (%rdi)
- movq %rax, 8(%rdi)
- movq %r8, 16(%rdi)
- movq %r11, 24(%rdi)
+ shlq %cl, %rax
+ movq %rax, (%r9)
+ movq %r8, 8(%r9)
+ movq %r10, 16(%r9)
+ movq %r13, 24(%r9)
+ popq %r13
+ popq %r12
repz retq
+#ifndef __APPLE__
+.size sp_2048_lshift_32,.-sp_2048_lshift_32
+#endif /* __APPLE__ */
#endif /* !WOLFSSL_SP_NO_2048 */
#endif /* !WOLFSSL_SP_NO_2048 */
#ifndef WOLFSSL_SP_NO_3072
@@ -12670,6 +12792,7 @@ L_3072_from_bin_bswap_zero_end:
#ifndef __APPLE__
.size sp_3072_from_bin_bswap,.-sp_3072_from_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Read big endian unsigned byte array into r.
* Uses the movbe instruction which is an optional instruction.
*
@@ -12755,6 +12878,7 @@ L_3072_from_bin_movbe_zero_end:
#ifndef __APPLE__
.size sp_3072_from_bin_movbe,.-sp_3072_from_bin_movbe
#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 384
* Uses the bswap instruction.
@@ -12922,6 +13046,7 @@ _sp_3072_to_bin_bswap:
#ifndef __APPLE__
.size sp_3072_to_bin_bswap,.-sp_3072_to_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 384
* Uses the movbe instruction which is optional.
@@ -13041,6 +13166,7 @@ _sp_3072_to_bin_movbe:
#ifndef __APPLE__
.size sp_3072_to_bin_movbe,.-sp_3072_to_bin_movbe
#endif /* __APPLE__ */
+#endif /* NO_MOVBE_SUPPORT */
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -14700,6 +14826,7 @@ _sp_3072_mul_avx2_12:
cmovne %rdi, %rbx
cmpq %rdi, %rbp
cmove %rsp, %rbx
+ addq $0x60, %rdi
xorq %r12, %r12
movq (%rsi), %rdx
# A[0] * B[0]
@@ -14752,7 +14879,7 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adcxq %r12, %r11
movq %r10, 88(%rbx)
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
movq 8(%rsi), %rdx
movq 8(%rbx), %r9
movq 16(%rbx), %r10
@@ -14815,7 +14942,7 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r9
adoxq %rcx, %r10
movq %r9, 80(%rbx)
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[1] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -14830,8 +14957,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r8, 96(%rdi)
- movq %r9, 104(%rdi)
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
movq 16(%rsi), %rdx
movq 16(%rbx), %r10
movq 24(%rbx), %r8
@@ -14883,7 +15010,7 @@ _sp_3072_mul_avx2_12:
adoxq %rcx, %r9
movq %r8, 72(%rbx)
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[2] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
@@ -14894,14 +15021,14 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r10
adoxq %rcx, %r8
movq %r10, 88(%rbx)
- movq 104(%rdi), %r9
+ movq 8(%rdi), %r9
# A[2] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[2] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
movq %r12, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
@@ -14909,8 +15036,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r9, 104(%rdi)
- movq %r10, 112(%rdi)
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
movq 24(%rsi), %rdx
movq 24(%rbx), %r8
movq 32(%rbx), %r9
@@ -14961,8 +15088,8 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r9
adoxq %rcx, %r10
movq %r9, 80(%rbx)
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[3] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -14972,15 +15099,15 @@ _sp_3072_mul_avx2_12:
movq %r10, 88(%rbx)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r10
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
# A[3] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[3] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
movq %r12, %r8
adcxq %rax, %r10
adoxq %rcx, %r8
@@ -14988,8 +15115,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r10, 112(%rdi)
- movq %r8, 120(%rdi)
+ movq %r10, 16(%rdi)
+ movq %r8, 24(%rdi)
movq 32(%rsi), %rdx
movq 32(%rbx), %r9
movq 40(%rbx), %r10
@@ -15029,7 +15156,7 @@ _sp_3072_mul_avx2_12:
adoxq %rcx, %r9
movq %r8, 72(%rbx)
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[4] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r9
@@ -15040,26 +15167,26 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r10
adoxq %rcx, %r8
movq %r10, 88(%rbx)
- movq 104(%rdi), %r9
- movq 112(%rdi), %r10
+ movq 8(%rdi), %r9
+ movq 16(%rdi), %r10
# A[4] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[4] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r8
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r8
# A[4] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[4] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r10, 112(%rdi)
+ movq %r10, 16(%rdi)
movq %r12, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
@@ -15067,8 +15194,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r8, 120(%rdi)
- movq %r9, 128(%rdi)
+ movq %r8, 24(%rdi)
+ movq %r9, 32(%rdi)
movq 40(%rsi), %rdx
movq 40(%rbx), %r10
movq 48(%rbx), %r8
@@ -15107,8 +15234,8 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r9
adoxq %rcx, %r10
movq %r9, 80(%rbx)
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[5] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -15118,27 +15245,27 @@ _sp_3072_mul_avx2_12:
movq %r10, 88(%rbx)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r10
- movq 120(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[5] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[5] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 112(%rdi)
- movq 128(%rdi), %r9
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
# A[5] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[5] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 120(%rdi)
+ movq %r8, 24(%rdi)
movq %r12, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
@@ -15146,8 +15273,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r9, 128(%rdi)
- movq %r10, 136(%rdi)
+ movq %r9, 32(%rdi)
+ movq %r10, 40(%rdi)
movq 48(%rsi), %rdx
movq 48(%rbx), %r8
movq 56(%rbx), %r9
@@ -15175,7 +15302,7 @@ _sp_3072_mul_avx2_12:
adoxq %rcx, %r9
movq %r8, 72(%rbx)
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[6] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r9
@@ -15186,38 +15313,38 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r10
adoxq %rcx, %r8
movq %r10, 88(%rbx)
- movq 104(%rdi), %r9
- movq 112(%rdi), %r10
+ movq 8(%rdi), %r9
+ movq 16(%rdi), %r10
# A[6] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[6] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r8
- movq 128(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r8
+ movq 32(%rdi), %r9
# A[6] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[6] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r10, 112(%rdi)
+ movq %r10, 16(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 120(%rdi)
- movq 136(%rdi), %r10
+ movq %r8, 24(%rdi)
+ movq 40(%rdi), %r10
# A[6] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[6] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, 32(%rdi)
movq %r12, %r8
adcxq %rax, %r10
adoxq %rcx, %r8
@@ -15225,8 +15352,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r10, 136(%rdi)
- movq %r8, 144(%rdi)
+ movq %r10, 40(%rdi)
+ movq %r8, 48(%rdi)
movq 56(%rsi), %rdx
movq 56(%rbx), %r9
movq 64(%rbx), %r10
@@ -15253,8 +15380,8 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r9
adoxq %rcx, %r10
movq %r9, 80(%rbx)
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[7] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -15264,39 +15391,39 @@ _sp_3072_mul_avx2_12:
movq %r10, 88(%rbx)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r10
- movq 120(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[7] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[7] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 112(%rdi)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq 40(%rdi), %r10
# A[7] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[7] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r8, 120(%rdi)
+ movq %r8, 24(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r8
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r8
# A[7] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[7] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 40(%rdi)
movq %r12, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
@@ -15304,8 +15431,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r8, 144(%rdi)
- movq %r9, 152(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
movq 64(%rsi), %rdx
movq 64(%rbx), %r10
movq 72(%rbx), %r8
@@ -15321,7 +15448,7 @@ _sp_3072_mul_avx2_12:
adoxq %rcx, %r9
movq %r8, 72(%rbx)
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[8] * B[2]
mulx 16(%rbp), %rax, %rcx
adcxq %rax, %r9
@@ -15332,50 +15459,50 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r10
adoxq %rcx, %r8
movq %r10, 88(%rbx)
- movq 104(%rdi), %r9
- movq 112(%rdi), %r10
+ movq 8(%rdi), %r9
+ movq 16(%rdi), %r10
# A[8] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[8] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r8
- movq 128(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r8
+ movq 32(%rdi), %r9
# A[8] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[8] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r10, 112(%rdi)
+ movq %r10, 16(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 120(%rdi)
- movq 136(%rdi), %r10
- movq 144(%rdi), %r8
+ movq %r8, 24(%rdi)
+ movq 40(%rdi), %r10
+ movq 48(%rdi), %r8
# A[8] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[8] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, 32(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 136(%rdi)
- movq 152(%rdi), %r9
+ movq %r10, 40(%rdi)
+ movq 56(%rdi), %r9
# A[8] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[8] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 144(%rdi)
+ movq %r8, 48(%rdi)
movq %r12, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
@@ -15383,8 +15510,8 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r9, 152(%rdi)
- movq %r10, 160(%rdi)
+ movq %r9, 56(%rdi)
+ movq %r10, 64(%rdi)
movq 72(%rsi), %rdx
movq 72(%rbx), %r8
movq 80(%rbx), %r9
@@ -15399,8 +15526,8 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r9
adoxq %rcx, %r10
movq %r9, 80(%rbx)
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[9] * B[2]
mulx 16(%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -15410,51 +15537,51 @@ _sp_3072_mul_avx2_12:
movq %r10, 88(%rbx)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r10
- movq 120(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[9] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[9] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 112(%rdi)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq 40(%rdi), %r10
# A[9] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[9] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r8, 120(%rdi)
+ movq %r8, 24(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
# A[9] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[9] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 40(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 144(%rdi)
- movq 160(%rdi), %r10
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r10
# A[9] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[9] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r9, 152(%rdi)
+ movq %r9, 56(%rdi)
movq %r12, %r8
adcxq %rax, %r10
adoxq %rcx, %r8
@@ -15462,12 +15589,12 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r10, 160(%rdi)
- movq %r8, 168(%rdi)
+ movq %r10, 64(%rdi)
+ movq %r8, 72(%rdi)
movq 80(%rsi), %rdx
movq 80(%rbx), %r9
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[10] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r9
@@ -15478,62 +15605,62 @@ _sp_3072_mul_avx2_12:
adcxq %rax, %r10
adoxq %rcx, %r8
movq %r10, 88(%rbx)
- movq 104(%rdi), %r9
- movq 112(%rdi), %r10
+ movq 8(%rdi), %r9
+ movq 16(%rdi), %r10
# A[10] * B[2]
mulx 16(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[10] * B[3]
mulx 24(%rbp), %rax, %rcx
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r8
- movq 128(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r8
+ movq 32(%rdi), %r9
# A[10] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[10] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r10, 112(%rdi)
+ movq %r10, 16(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 120(%rdi)
- movq 136(%rdi), %r10
- movq 144(%rdi), %r8
+ movq %r8, 24(%rdi)
+ movq 40(%rdi), %r10
+ movq 48(%rdi), %r8
# A[10] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[10] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r9, 128(%rdi)
+ movq %r9, 32(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 136(%rdi)
- movq 152(%rdi), %r9
- movq 160(%rdi), %r10
+ movq %r10, 40(%rdi)
+ movq 56(%rdi), %r9
+ movq 64(%rdi), %r10
# A[10] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[10] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r8, 144(%rdi)
+ movq %r8, 48(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 152(%rdi)
- movq 168(%rdi), %r8
+ movq %r9, 56(%rdi)
+ movq 72(%rdi), %r8
# A[10] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[10] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r10, 160(%rdi)
+ movq %r10, 64(%rdi)
movq %r12, %r9
adcxq %rax, %r8
adoxq %rcx, %r9
@@ -15541,12 +15668,12 @@ _sp_3072_mul_avx2_12:
movq %r12, %r11
adoxq %r12, %r11
adcxq %r12, %r11
- movq %r8, 168(%rdi)
- movq %r9, 176(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
movq 88(%rsi), %rdx
movq 88(%rbx), %r10
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[11] * B[0]
mulx (%rbp), %rax, %rcx
adcxq %rax, %r10
@@ -15556,69 +15683,70 @@ _sp_3072_mul_avx2_12:
movq %r10, 88(%rbx)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r10
- movq 120(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
# A[11] * B[2]
mulx 16(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[11] * B[3]
mulx 24(%rbp), %rax, %rcx
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 112(%rdi)
- movq 128(%rdi), %r9
- movq 136(%rdi), %r10
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq 40(%rdi), %r10
# A[11] * B[4]
mulx 32(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[11] * B[5]
mulx 40(%rbp), %rax, %rcx
- movq %r8, 120(%rdi)
+ movq %r8, 24(%rdi)
adcxq %rax, %r9
adoxq %rcx, %r10
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
# A[11] * B[6]
mulx 48(%rbp), %rax, %rcx
adcxq %rax, %r10
adoxq %rcx, %r8
# A[11] * B[7]
mulx 56(%rbp), %rax, %rcx
- movq %r10, 136(%rdi)
+ movq %r10, 40(%rdi)
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 144(%rdi)
- movq 160(%rdi), %r10
- movq 168(%rdi), %r8
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r10
+ movq 72(%rdi), %r8
# A[11] * B[8]
mulx 64(%rbp), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r10
# A[11] * B[9]
mulx 72(%rbp), %rax, %rcx
- movq %r9, 152(%rdi)
+ movq %r9, 56(%rdi)
adcxq %rax, %r10
adoxq %rcx, %r8
- movq %r10, 160(%rdi)
- movq 176(%rdi), %r9
+ movq %r10, 64(%rdi)
+ movq 80(%rdi), %r9
# A[11] * B[10]
mulx 80(%rbp), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
# A[11] * B[11]
mulx 88(%rbp), %rax, %rcx
- movq %r8, 168(%rdi)
+ movq %r8, 72(%rdi)
movq %r12, %r10
adcxq %rax, %r9
adoxq %rcx, %r10
adcxq %r11, %r10
- movq %r9, 176(%rdi)
- movq %r10, 184(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ subq $0x60, %rdi
cmpq %rdi, %rsi
je L_start_3072_mul_avx2_12
cmpq %rdi, %rbp
@@ -15674,6 +15802,7 @@ _sp_3072_sqr_avx2_12:
cmpq %rdi, %rsi
movq %rsp, %rbp
cmovne %rdi, %rbp
+ addq $0x60, %rdi
xorq %r10, %r10
# Diagonal 1
# A[1] x A[0]
@@ -15745,7 +15874,7 @@ _sp_3072_sqr_avx2_12:
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r9, 96(%rdi)
+ movq %r9, (%rdi)
# Diagonal 2
movq 24(%rbp), %r9
movq 32(%rbp), %r8
@@ -15797,7 +15926,7 @@ _sp_3072_sqr_avx2_12:
adcxq %rax, %r15
adoxq %rcx, %rbx
# No store %r15
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[10] x A[1]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %rbx
@@ -15808,20 +15937,20 @@ _sp_3072_sqr_avx2_12:
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
+ movq %r8, (%rdi)
movq %r10, %r8
# A[11] x A[2]
movq 16(%rsi), %rdx
mulxq 88(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 104(%rdi)
+ movq %r9, 8(%rdi)
# Carry
adcxq %r11, %r8
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r8, 112(%rdi)
+ movq %r8, 16(%rdi)
# Diagonal 3
movq 40(%rbp), %r8
movq 48(%rbp), %r9
@@ -15860,43 +15989,43 @@ _sp_3072_sqr_avx2_12:
adcxq %rax, %r15
adoxq %rcx, %rbx
# No store %r15
- movq 96(%rdi), %r9
+ movq (%rdi), %r9
# A[9] x A[2]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %rbx
adoxq %rcx, %r9
# No store %rbx
- movq 104(%rdi), %r8
+ movq 8(%rdi), %r8
# A[10] x A[2]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 96(%rdi)
- movq 112(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r9
# A[10] x A[3]
movq 80(%rsi), %rdx
mulxq 24(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 104(%rdi)
+ movq %r8, 8(%rdi)
movq %r10, %r8
# A[10] x A[4]
mulxq 32(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 112(%rdi)
+ movq %r9, 16(%rdi)
movq %r10, %r9
# A[10] x A[5]
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 120(%rdi)
+ movq %r8, 24(%rdi)
# Carry
adcxq %r11, %r9
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r9, 128(%rdi)
+ movq %r9, 32(%rdi)
# Diagonal 4
# No load %r12 - %r9
# No load %r13 - %r8
@@ -15924,55 +16053,55 @@ _sp_3072_sqr_avx2_12:
adcxq %rax, %r15
adoxq %rcx, %rbx
# No store %r15
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[8] x A[3]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %rbx
adoxq %rcx, %r8
# No store %rbx
- movq 104(%rdi), %r9
+ movq 8(%rdi), %r9
# A[9] x A[3]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r8
# A[9] x A[4]
movq 72(%rsi), %rdx
mulxq 32(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r9
# A[9] x A[5]
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 112(%rdi)
- movq 128(%rdi), %r8
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r8
# A[9] x A[6]
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 120(%rdi)
+ movq %r9, 24(%rdi)
movq %r10, %r9
# A[9] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 128(%rdi)
+ movq %r8, 32(%rdi)
movq %r10, %r8
# A[9] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 136(%rdi)
+ movq %r9, 40(%rdi)
# Carry
adcxq %r11, %r8
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r8, 144(%rdi)
+ movq %r8, 48(%rdi)
# Diagonal 5
# No load %r14 - %r8
# No load %r15 - %r9
@@ -15988,146 +16117,146 @@ _sp_3072_sqr_avx2_12:
adcxq %rax, %r15
adoxq %rcx, %rbx
# No store %r15
- movq 96(%rdi), %r9
+ movq (%rdi), %r9
# A[7] x A[4]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %rbx
adoxq %rcx, %r9
# No store %rbx
- movq 104(%rdi), %r8
+ movq 8(%rdi), %r8
# A[8] x A[4]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 96(%rdi)
- movq 112(%rdi), %r9
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r9
# A[8] x A[5]
movq 64(%rsi), %rdx
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 104(%rdi)
- movq 120(%rdi), %r8
+ movq %r8, 8(%rdi)
+ movq 24(%rdi), %r8
# A[8] x A[6]
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 112(%rdi)
- movq 128(%rdi), %r9
+ movq %r9, 16(%rdi)
+ movq 32(%rdi), %r9
# A[8] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 120(%rdi)
- movq 136(%rdi), %r8
+ movq %r8, 24(%rdi)
+ movq 40(%rdi), %r8
# A[10] x A[6]
movq 80(%rsi), %rdx
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 128(%rdi)
- movq 144(%rdi), %r9
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r9
# A[10] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 136(%rdi)
+ movq %r8, 40(%rdi)
movq %r10, %r8
# A[10] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 144(%rdi)
+ movq %r9, 48(%rdi)
movq %r10, %r9
# A[10] x A[9]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 152(%rdi)
+ movq %r8, 56(%rdi)
# Carry
adcxq %r11, %r9
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r9, 160(%rdi)
+ movq %r9, 64(%rdi)
# Diagonal 6
# No load %rbx - %r9
- movq 96(%rdi), %r8
+ movq (%rdi), %r8
# A[6] x A[5]
movq 40(%rsi), %rdx
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %rbx
adoxq %rcx, %r8
# No store %rbx
- movq 104(%rdi), %r9
+ movq 8(%rdi), %r9
# A[7] x A[5]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq 112(%rdi), %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r8
# A[7] x A[6]
movq 48(%rsi), %rdx
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 104(%rdi)
- movq 120(%rdi), %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r9
# A[11] x A[3]
movq 88(%rsi), %rdx
mulxq 24(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 112(%rdi)
- movq 128(%rdi), %r8
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r8
# A[11] x A[4]
mulxq 32(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 120(%rdi)
- movq 136(%rdi), %r9
+ movq %r9, 24(%rdi)
+ movq 40(%rdi), %r9
# A[11] x A[5]
mulxq 40(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 128(%rdi)
- movq 144(%rdi), %r8
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r8
# A[11] x A[6]
mulxq 48(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 136(%rdi)
- movq 152(%rdi), %r9
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r9
# A[11] x A[7]
mulxq 56(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 144(%rdi)
- movq 160(%rdi), %r8
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r8
# A[11] x A[8]
mulxq 64(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 152(%rdi)
+ movq %r9, 56(%rdi)
movq %r10, %r9
# A[11] x A[9]
mulxq 72(%rsi), %rax, %rcx
adcxq %rax, %r8
adoxq %rcx, %r9
- movq %r8, 160(%rdi)
+ movq %r8, 64(%rdi)
movq %r10, %r8
# A[11] x A[10]
mulxq 80(%rsi), %rax, %rcx
adcxq %rax, %r9
adoxq %rcx, %r8
- movq %r9, 168(%rdi)
+ movq %r9, 72(%rdi)
# Carry
adcxq %r11, %r8
movq %r10, %r11
adcxq %r10, %r11
adoxq %r10, %r11
- movq %r8, 176(%rdi)
- movq %r11, 184(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r11, 88(%rdi)
# Double and Add in A[i] x A[i]
movq 8(%rbp), %r9
# A[0] x A[0]
@@ -16182,8 +16311,8 @@ _sp_3072_sqr_avx2_12:
adoxq %rbx, %rbx
adcxq %rax, %r15
adcxq %rcx, %rbx
- movq 96(%rdi), %r8
- movq 104(%rdi), %r9
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
# A[6] x A[6]
movq 48(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16191,10 +16320,10 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 96(%rdi)
- movq %r9, 104(%rdi)
- movq 112(%rdi), %r8
- movq 120(%rdi), %r9
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
# A[7] x A[7]
movq 56(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16202,10 +16331,10 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 112(%rdi)
- movq %r9, 120(%rdi)
- movq 128(%rdi), %r8
- movq 136(%rdi), %r9
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
# A[8] x A[8]
movq 64(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16213,10 +16342,10 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 128(%rdi)
- movq %r9, 136(%rdi)
- movq 144(%rdi), %r8
- movq 152(%rdi), %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
# A[9] x A[9]
movq 72(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16224,10 +16353,10 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 144(%rdi)
- movq %r9, 152(%rdi)
- movq 160(%rdi), %r8
- movq 168(%rdi), %r9
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
# A[10] x A[10]
movq 80(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16235,10 +16364,10 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 160(%rdi)
- movq %r9, 168(%rdi)
- movq 176(%rdi), %r8
- movq 184(%rdi), %r9
+ movq %r8, 64(%rdi)
+ movq %r9, 72(%rdi)
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
# A[11] x A[11]
movq 88(%rsi), %rdx
mulxq %rdx, %rax, %rcx
@@ -16246,13 +16375,14 @@ _sp_3072_sqr_avx2_12:
adoxq %r9, %r9
adcxq %rax, %r8
adcxq %rcx, %r9
- movq %r8, 176(%rdi)
- movq %r9, 184(%rdi)
- movq %r12, 56(%rdi)
- movq %r13, 64(%rdi)
- movq %r14, 72(%rdi)
- movq %r15, 80(%rdi)
- movq %rbx, 88(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq %r12, -40(%rdi)
+ movq %r13, -32(%rdi)
+ movq %r14, -24(%rdi)
+ movq %r15, -16(%rdi)
+ movq %rbx, -8(%rdi)
+ subq $0x60, %rdi
cmpq %rdi, %rsi
jne L_end_3072_sqr_avx2_12
vmovdqu (%rbp), %xmm0
@@ -16665,6 +16795,11 @@ _sp_3072_mul_24:
#else
callq _sp_3072_mul_12
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 592(%rsp), %rdx
+ movq 584(%rsp), %rsi
+ movq 576(%rsp), %rdi
+#endif /* _WIN64 */
movq 600(%rsp), %r13
movq 608(%rsp), %r14
movq 576(%rsp), %r15
@@ -17235,6 +17370,10 @@ _sp_3072_sqr_24:
#else
callq _sp_3072_sqr_12
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 488(%rsp), %rsi
+ movq 480(%rsp), %rdi
+#endif /* _WIN64 */
movq 496(%rsp), %r10
movq %rdi, %r9
leaq 384(%rsp), %r8
@@ -17617,6 +17756,7 @@ _sp_3072_sqr_24:
#ifndef __APPLE__
.size sp_3072_sqr_24,.-sp_3072_sqr_24
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -17753,6 +17893,11 @@ _sp_3072_mul_avx2_24:
#else
callq _sp_3072_mul_avx2_12
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 592(%rsp), %rdx
+ movq 584(%rsp), %rsi
+ movq 576(%rsp), %rdi
+#endif /* _WIN64 */
movq 600(%rsp), %r13
movq 608(%rsp), %r14
movq 576(%rsp), %r15
@@ -18144,6 +18289,8 @@ _sp_3072_mul_avx2_24:
#ifndef __APPLE__
.size sp_3072_mul_avx2_24,.-sp_3072_mul_avx2_24
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square a and put result in r. (r = a * a)
*
* r A single precision integer.
@@ -18228,6 +18375,10 @@ _sp_3072_sqr_avx2_24:
#else
callq _sp_3072_sqr_avx2_12
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 488(%rsp), %rsi
+ movq 480(%rsp), %rdi
+#endif /* _WIN64 */
movq 496(%rsp), %r10
movq %rdi, %r9
leaq 384(%rsp), %r8
@@ -18586,6 +18737,7 @@ _sp_3072_sqr_avx2_24:
#ifndef __APPLE__
.size sp_3072_sqr_avx2_24,.-sp_3072_sqr_avx2_24
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Sub b from a into a. (a -= b)
*
* a A single precision integer and result.
@@ -19130,6 +19282,11 @@ _sp_3072_mul_48:
#else
callq _sp_3072_mul_24
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1168(%rsp), %rdx
+ movq 1160(%rsp), %rsi
+ movq 1152(%rsp), %rdi
+#endif /* _WIN64 */
movq 1176(%rsp), %r13
movq 1184(%rsp), %r14
movq 1152(%rsp), %r15
@@ -20168,6 +20325,10 @@ _sp_3072_sqr_48:
#else
callq _sp_3072_sqr_24
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 968(%rsp), %rsi
+ movq 960(%rsp), %rdi
+#endif /* _WIN64 */
movq 976(%rsp), %r10
movq %rdi, %r9
leaq 768(%rsp), %r8
@@ -20910,6 +21071,7 @@ _sp_3072_sqr_48:
#ifndef __APPLE__
.size sp_3072_sqr_48,.-sp_3072_sqr_48
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -21118,6 +21280,11 @@ _sp_3072_mul_avx2_48:
#else
callq _sp_3072_mul_avx2_24
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1168(%rsp), %rdx
+ movq 1160(%rsp), %rsi
+ movq 1152(%rsp), %rdi
+#endif /* _WIN64 */
movq 1176(%rsp), %r13
movq 1184(%rsp), %r14
movq 1152(%rsp), %r15
@@ -21869,6 +22036,8 @@ _sp_3072_mul_avx2_48:
#ifndef __APPLE__
.size sp_3072_mul_avx2_48,.-sp_3072_mul_avx2_48
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square a and put result in r. (r = a * a)
*
* r A single precision integer.
@@ -21989,6 +22158,10 @@ _sp_3072_sqr_avx2_48:
#else
callq _sp_3072_sqr_avx2_24
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 968(%rsp), %rsi
+ movq 960(%rsp), %rdi
+#endif /* _WIN64 */
movq 976(%rsp), %r10
movq %rdi, %r9
leaq 768(%rsp), %r8
@@ -22683,6 +22856,7 @@ _sp_3072_sqr_avx2_48:
#ifndef __APPLE__
.size sp_3072_sqr_avx2_48,.-sp_3072_sqr_avx2_48
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -23312,7 +23486,7 @@ _sp_3072_mont_reduce_24:
movq $24, %r8
movq (%rdi), %r13
movq 8(%rdi), %r14
-L_mont_loop_24:
+L_3072_mont_loop_24:
# mu = a[i] * mp
movq %r13, %r11
imulq %rcx, %r11
@@ -23555,12 +23729,17 @@ L_mont_loop_24:
# i -= 1
addq $8, %rdi
decq %r8
- jnz L_mont_loop_24
+ jnz L_3072_mont_loop_24
movq %r13, (%rdi)
movq %r14, 8(%rdi)
negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
movq %r15, %rcx
movq %rsi, %rdx
+#endif /* _WIN64 */
movq %rdi, %rsi
movq %rdi, %rdi
subq $0xc0, %rdi
@@ -23577,6 +23756,7 @@ L_mont_loop_24:
#ifndef __APPLE__
.size sp_3072_mont_reduce_24,.-sp_3072_mont_reduce_24
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -23723,6 +23903,7 @@ _sp_3072_cond_sub_avx2_24:
#ifndef __APPLE__
.size sp_3072_cond_sub_avx2_24,.-sp_3072_cond_sub_avx2_24
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -23965,134 +24146,134 @@ _sp_3072_mul_d_avx2_24:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 40(%rdi)
adoxq %r8, %r9
+ movq %r10, 40(%rdi)
# A[6] * B
mulxq 48(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 48(%rdi)
adoxq %r8, %r10
+ movq %r9, 48(%rdi)
# A[7] * B
mulxq 56(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 56(%rdi)
adoxq %r8, %r9
+ movq %r10, 56(%rdi)
# A[8] * B
mulxq 64(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 64(%rdi)
adoxq %r8, %r10
+ movq %r9, 64(%rdi)
# A[9] * B
mulxq 72(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 72(%rdi)
adoxq %r8, %r9
+ movq %r10, 72(%rdi)
# A[10] * B
mulxq 80(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 80(%rdi)
adoxq %r8, %r10
+ movq %r9, 80(%rdi)
# A[11] * B
mulxq 88(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 88(%rdi)
adoxq %r8, %r9
+ movq %r10, 88(%rdi)
# A[12] * B
mulxq 96(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 96(%rdi)
adoxq %r8, %r10
+ movq %r9, 96(%rdi)
# A[13] * B
mulxq 104(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 104(%rdi)
adoxq %r8, %r9
+ movq %r10, 104(%rdi)
# A[14] * B
mulxq 112(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 112(%rdi)
adoxq %r8, %r10
+ movq %r9, 112(%rdi)
# A[15] * B
mulxq 120(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 120(%rdi)
adoxq %r8, %r9
+ movq %r10, 120(%rdi)
# A[16] * B
mulxq 128(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 128(%rdi)
adoxq %r8, %r10
+ movq %r9, 128(%rdi)
# A[17] * B
mulxq 136(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 136(%rdi)
adoxq %r8, %r9
+ movq %r10, 136(%rdi)
# A[18] * B
mulxq 144(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 144(%rdi)
adoxq %r8, %r10
+ movq %r9, 144(%rdi)
# A[19] * B
mulxq 152(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 152(%rdi)
adoxq %r8, %r9
+ movq %r10, 152(%rdi)
# A[20] * B
mulxq 160(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 160(%rdi)
adoxq %r8, %r10
+ movq %r9, 160(%rdi)
# A[21] * B
mulxq 168(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 168(%rdi)
adoxq %r8, %r9
+ movq %r10, 168(%rdi)
# A[22] * B
mulxq 176(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 176(%rdi)
adoxq %r8, %r10
+ movq %r9, 176(%rdi)
# A[23] * B
mulxq 184(%rsi), %rcx, %r8
movq %r11, %r9
@@ -24106,6 +24287,35 @@ _sp_3072_mul_d_avx2_24:
.size sp_3072_mul_d_avx2_24,.-sp_3072_mul_d_avx2_24
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_3072_word_asm_24
+.type div_3072_word_asm_24,@function
+.align 16
+div_3072_word_asm_24:
+#else
+.section __TEXT,__text
+.globl _div_3072_word_asm_24
+.p2align 4
+_div_3072_word_asm_24:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_3072_word_asm_24,.-div_3072_word_asm_24
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -24348,14 +24558,20 @@ _sp_3072_mont_reduce_avx2_24:
pushq %r12
pushq %r13
pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
movq %rdx, %r8
- xorq %r14, %r14
+ xorq %rbp, %rbp
# i = 24
movq $24, %r9
movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
addq $0x60, %rdi
- xorq %r12, %r12
-L_mont_loop_avx2_24:
+ xorq %rbp, %rbp
+L_3072_mont_loop_avx2_24:
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -24363,32 +24579,29 @@ L_mont_loop_avx2_24:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -88(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -80(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -72(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -80(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -64(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -72(%rdi)
+ movq -64(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -56(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -64(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -48(%rdi), %r10
@@ -24503,140 +24716,143 @@ L_mont_loop_avx2_24:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 88(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 96(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# a += 1
addq $8, %rdi
# i -= 1
subq $0x01, %r9
- jnz L_mont_loop_avx2_24
+ jnz L_3072_mont_loop_avx2_24
subq $0x60, %rdi
- negq %r14
+ negq %rbp
movq %rdi, %r8
subq $0xc0, %rdi
movq (%rsi), %rcx
movq %r13, %rdx
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
subq %rcx, %rdx
movq 8(%rsi), %rcx
- movq 8(%r8), %rax
- pextq %r14, %rcx, %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
movq %rdx, (%rdi)
sbbq %rcx, %rax
movq 16(%rsi), %rdx
- movq 16(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
movq %rax, 8(%rdi)
sbbq %rdx, %rcx
movq 24(%rsi), %rax
- movq 24(%r8), %rdx
- pextq %r14, %rax, %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
movq %rcx, 16(%rdi)
sbbq %rax, %rdx
movq 32(%rsi), %rcx
movq 32(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 24(%rdi)
sbbq %rcx, %rax
movq 40(%rsi), %rdx
movq 40(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 32(%rdi)
sbbq %rdx, %rcx
movq 48(%rsi), %rax
movq 48(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 40(%rdi)
sbbq %rax, %rdx
movq 56(%rsi), %rcx
movq 56(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 48(%rdi)
sbbq %rcx, %rax
movq 64(%rsi), %rdx
movq 64(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 56(%rdi)
sbbq %rdx, %rcx
movq 72(%rsi), %rax
movq 72(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 64(%rdi)
sbbq %rax, %rdx
movq 80(%rsi), %rcx
movq 80(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 72(%rdi)
sbbq %rcx, %rax
movq 88(%rsi), %rdx
movq 88(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 80(%rdi)
sbbq %rdx, %rcx
movq 96(%rsi), %rax
movq 96(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 88(%rdi)
sbbq %rax, %rdx
movq 104(%rsi), %rcx
movq 104(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 96(%rdi)
sbbq %rcx, %rax
movq 112(%rsi), %rdx
movq 112(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 104(%rdi)
sbbq %rdx, %rcx
movq 120(%rsi), %rax
movq 120(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 112(%rdi)
sbbq %rax, %rdx
movq 128(%rsi), %rcx
movq 128(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 120(%rdi)
sbbq %rcx, %rax
movq 136(%rsi), %rdx
movq 136(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 128(%rdi)
sbbq %rdx, %rcx
movq 144(%rsi), %rax
movq 144(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 136(%rdi)
sbbq %rax, %rdx
movq 152(%rsi), %rcx
movq 152(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 144(%rdi)
sbbq %rcx, %rax
movq 160(%rsi), %rdx
movq 160(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 152(%rdi)
sbbq %rdx, %rcx
movq 168(%rsi), %rax
movq 168(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 160(%rdi)
sbbq %rax, %rdx
movq 176(%rsi), %rcx
movq 176(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 168(%rdi)
sbbq %rcx, %rax
movq 184(%rsi), %rdx
movq 184(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 176(%rdi)
sbbq %rdx, %rcx
movq %rcx, 184(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
popq %r14
popq %r13
popq %r12
@@ -25037,7 +25253,7 @@ _sp_3072_mont_reduce_48:
movq $48, %r8
movq (%rdi), %r13
movq 8(%rdi), %r14
-L_mont_loop_48:
+L_3072_mont_loop_48:
# mu = a[i] * mp
movq %r13, %r11
imulq %rcx, %r11
@@ -25520,12 +25736,17 @@ L_mont_loop_48:
# i -= 1
addq $8, %rdi
decq %r8
- jnz L_mont_loop_48
+ jnz L_3072_mont_loop_48
movq %r13, (%rdi)
movq %r14, 8(%rdi)
negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
movq %r15, %rcx
movq %rsi, %rdx
+#endif /* _WIN64 */
movq %rdi, %rsi
movq %rdi, %rdi
subq $0x180, %rdi
@@ -25542,6 +25763,7 @@ L_mont_loop_48:
#ifndef __APPLE__
.size sp_3072_mont_reduce_48,.-sp_3072_mont_reduce_48
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -25808,6 +26030,7 @@ _sp_3072_cond_sub_avx2_48:
#ifndef __APPLE__
.size sp_3072_cond_sub_avx2_48,.-sp_3072_cond_sub_avx2_48
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifdef HAVE_INTEL_AVX2
/* Mul a by digit b into r. (r = a * b)
*
@@ -25837,278 +26060,278 @@ _sp_3072_mul_d_avx2_48:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 40(%rdi)
adoxq %r8, %r9
+ movq %r10, 40(%rdi)
# A[6] * B
mulxq 48(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 48(%rdi)
adoxq %r8, %r10
+ movq %r9, 48(%rdi)
# A[7] * B
mulxq 56(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 56(%rdi)
adoxq %r8, %r9
+ movq %r10, 56(%rdi)
# A[8] * B
mulxq 64(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 64(%rdi)
adoxq %r8, %r10
+ movq %r9, 64(%rdi)
# A[9] * B
mulxq 72(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 72(%rdi)
adoxq %r8, %r9
+ movq %r10, 72(%rdi)
# A[10] * B
mulxq 80(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 80(%rdi)
adoxq %r8, %r10
+ movq %r9, 80(%rdi)
# A[11] * B
mulxq 88(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 88(%rdi)
adoxq %r8, %r9
+ movq %r10, 88(%rdi)
# A[12] * B
mulxq 96(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 96(%rdi)
adoxq %r8, %r10
+ movq %r9, 96(%rdi)
# A[13] * B
mulxq 104(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 104(%rdi)
adoxq %r8, %r9
+ movq %r10, 104(%rdi)
# A[14] * B
mulxq 112(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 112(%rdi)
adoxq %r8, %r10
+ movq %r9, 112(%rdi)
# A[15] * B
mulxq 120(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 120(%rdi)
adoxq %r8, %r9
+ movq %r10, 120(%rdi)
# A[16] * B
mulxq 128(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 128(%rdi)
adoxq %r8, %r10
+ movq %r9, 128(%rdi)
# A[17] * B
mulxq 136(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 136(%rdi)
adoxq %r8, %r9
+ movq %r10, 136(%rdi)
# A[18] * B
mulxq 144(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 144(%rdi)
adoxq %r8, %r10
+ movq %r9, 144(%rdi)
# A[19] * B
mulxq 152(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 152(%rdi)
adoxq %r8, %r9
+ movq %r10, 152(%rdi)
# A[20] * B
mulxq 160(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 160(%rdi)
adoxq %r8, %r10
+ movq %r9, 160(%rdi)
# A[21] * B
mulxq 168(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 168(%rdi)
adoxq %r8, %r9
+ movq %r10, 168(%rdi)
# A[22] * B
mulxq 176(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 176(%rdi)
adoxq %r8, %r10
+ movq %r9, 176(%rdi)
# A[23] * B
mulxq 184(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 184(%rdi)
adoxq %r8, %r9
+ movq %r10, 184(%rdi)
# A[24] * B
mulxq 192(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 192(%rdi)
adoxq %r8, %r10
+ movq %r9, 192(%rdi)
# A[25] * B
mulxq 200(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 200(%rdi)
adoxq %r8, %r9
+ movq %r10, 200(%rdi)
# A[26] * B
mulxq 208(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 208(%rdi)
adoxq %r8, %r10
+ movq %r9, 208(%rdi)
# A[27] * B
mulxq 216(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 216(%rdi)
adoxq %r8, %r9
+ movq %r10, 216(%rdi)
# A[28] * B
mulxq 224(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 224(%rdi)
adoxq %r8, %r10
+ movq %r9, 224(%rdi)
# A[29] * B
mulxq 232(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 232(%rdi)
adoxq %r8, %r9
+ movq %r10, 232(%rdi)
# A[30] * B
mulxq 240(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 240(%rdi)
adoxq %r8, %r10
+ movq %r9, 240(%rdi)
# A[31] * B
mulxq 248(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 248(%rdi)
adoxq %r8, %r9
+ movq %r10, 248(%rdi)
# A[32] * B
mulxq 256(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 256(%rdi)
adoxq %r8, %r10
+ movq %r9, 256(%rdi)
# A[33] * B
mulxq 264(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 264(%rdi)
adoxq %r8, %r9
+ movq %r10, 264(%rdi)
# A[34] * B
mulxq 272(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 272(%rdi)
adoxq %r8, %r10
+ movq %r9, 272(%rdi)
# A[35] * B
mulxq 280(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 280(%rdi)
adoxq %r8, %r9
+ movq %r10, 280(%rdi)
# A[36] * B
mulxq 288(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 288(%rdi)
adoxq %r8, %r10
+ movq %r9, 288(%rdi)
# A[37] * B
mulxq 296(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 296(%rdi)
adoxq %r8, %r9
+ movq %r10, 296(%rdi)
# A[38] * B
mulxq 304(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 304(%rdi)
adoxq %r8, %r10
+ movq %r9, 304(%rdi)
# A[39] * B
mulxq 312(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 312(%rdi)
adoxq %r8, %r9
+ movq %r10, 312(%rdi)
# A[40] * B
mulxq 320(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 320(%rdi)
adoxq %r8, %r10
+ movq %r9, 320(%rdi)
# A[41] * B
mulxq 328(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 328(%rdi)
adoxq %r8, %r9
+ movq %r10, 328(%rdi)
# A[42] * B
mulxq 336(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 336(%rdi)
adoxq %r8, %r10
+ movq %r9, 336(%rdi)
# A[43] * B
mulxq 344(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 344(%rdi)
adoxq %r8, %r9
+ movq %r10, 344(%rdi)
# A[44] * B
mulxq 352(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 352(%rdi)
adoxq %r8, %r10
+ movq %r9, 352(%rdi)
# A[45] * B
mulxq 360(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 360(%rdi)
adoxq %r8, %r9
+ movq %r10, 360(%rdi)
# A[46] * B
mulxq 368(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 368(%rdi)
adoxq %r8, %r10
+ movq %r9, 368(%rdi)
# A[47] * B
mulxq 376(%rsi), %rcx, %r8
movq %r11, %r9
@@ -26122,6 +26345,35 @@ _sp_3072_mul_d_avx2_48:
.size sp_3072_mul_d_avx2_48,.-sp_3072_mul_d_avx2_48
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_3072_word_asm_48
+.type div_3072_word_asm_48,@function
+.align 16
+div_3072_word_asm_48:
+#else
+.section __TEXT,__text
+.globl _div_3072_word_asm_48
+.p2align 4
+_div_3072_word_asm_48:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_3072_word_asm_48,.-div_3072_word_asm_48
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -26724,14 +26976,20 @@ _sp_3072_mont_reduce_avx2_48:
pushq %r12
pushq %r13
pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
movq %rdx, %r8
- xorq %r14, %r14
+ xorq %rbp, %rbp
# i = 48
movq $48, %r9
movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
addq $0xc0, %rdi
- xorq %r12, %r12
-L_mont_loop_avx2_48:
+ xorq %rbp, %rbp
+L_3072_mont_loop_avx2_48:
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -26739,32 +26997,29 @@ L_mont_loop_avx2_48:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -184(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -176(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -168(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -176(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -160(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -168(%rdi)
+ movq -160(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -152(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -160(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -144(%rdi), %r10
@@ -27023,260 +27278,263 @@ L_mont_loop_avx2_48:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 184(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 192(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# a += 1
addq $8, %rdi
# i -= 1
subq $0x01, %r9
- jnz L_mont_loop_avx2_48
+ jnz L_3072_mont_loop_avx2_48
subq $0xc0, %rdi
- negq %r14
+ negq %rbp
movq %rdi, %r8
subq $0x180, %rdi
movq (%rsi), %rcx
movq %r13, %rdx
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
subq %rcx, %rdx
movq 8(%rsi), %rcx
- movq 8(%r8), %rax
- pextq %r14, %rcx, %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
movq %rdx, (%rdi)
sbbq %rcx, %rax
movq 16(%rsi), %rdx
- movq 16(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
movq %rax, 8(%rdi)
sbbq %rdx, %rcx
movq 24(%rsi), %rax
- movq 24(%r8), %rdx
- pextq %r14, %rax, %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
movq %rcx, 16(%rdi)
sbbq %rax, %rdx
movq 32(%rsi), %rcx
movq 32(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 24(%rdi)
sbbq %rcx, %rax
movq 40(%rsi), %rdx
movq 40(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 32(%rdi)
sbbq %rdx, %rcx
movq 48(%rsi), %rax
movq 48(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 40(%rdi)
sbbq %rax, %rdx
movq 56(%rsi), %rcx
movq 56(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 48(%rdi)
sbbq %rcx, %rax
movq 64(%rsi), %rdx
movq 64(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 56(%rdi)
sbbq %rdx, %rcx
movq 72(%rsi), %rax
movq 72(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 64(%rdi)
sbbq %rax, %rdx
movq 80(%rsi), %rcx
movq 80(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 72(%rdi)
sbbq %rcx, %rax
movq 88(%rsi), %rdx
movq 88(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 80(%rdi)
sbbq %rdx, %rcx
movq 96(%rsi), %rax
movq 96(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 88(%rdi)
sbbq %rax, %rdx
movq 104(%rsi), %rcx
movq 104(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 96(%rdi)
sbbq %rcx, %rax
movq 112(%rsi), %rdx
movq 112(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 104(%rdi)
sbbq %rdx, %rcx
movq 120(%rsi), %rax
movq 120(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 112(%rdi)
sbbq %rax, %rdx
movq 128(%rsi), %rcx
movq 128(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 120(%rdi)
sbbq %rcx, %rax
movq 136(%rsi), %rdx
movq 136(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 128(%rdi)
sbbq %rdx, %rcx
movq 144(%rsi), %rax
movq 144(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 136(%rdi)
sbbq %rax, %rdx
movq 152(%rsi), %rcx
movq 152(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 144(%rdi)
sbbq %rcx, %rax
movq 160(%rsi), %rdx
movq 160(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 152(%rdi)
sbbq %rdx, %rcx
movq 168(%rsi), %rax
movq 168(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 160(%rdi)
sbbq %rax, %rdx
movq 176(%rsi), %rcx
movq 176(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 168(%rdi)
sbbq %rcx, %rax
movq 184(%rsi), %rdx
movq 184(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 176(%rdi)
sbbq %rdx, %rcx
movq 192(%rsi), %rax
movq 192(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 184(%rdi)
sbbq %rax, %rdx
movq 200(%rsi), %rcx
movq 200(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 192(%rdi)
sbbq %rcx, %rax
movq 208(%rsi), %rdx
movq 208(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 200(%rdi)
sbbq %rdx, %rcx
movq 216(%rsi), %rax
movq 216(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 208(%rdi)
sbbq %rax, %rdx
movq 224(%rsi), %rcx
movq 224(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 216(%rdi)
sbbq %rcx, %rax
movq 232(%rsi), %rdx
movq 232(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 224(%rdi)
sbbq %rdx, %rcx
movq 240(%rsi), %rax
movq 240(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 232(%rdi)
sbbq %rax, %rdx
movq 248(%rsi), %rcx
movq 248(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 240(%rdi)
sbbq %rcx, %rax
movq 256(%rsi), %rdx
movq 256(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 248(%rdi)
sbbq %rdx, %rcx
movq 264(%rsi), %rax
movq 264(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 256(%rdi)
sbbq %rax, %rdx
movq 272(%rsi), %rcx
movq 272(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 264(%rdi)
sbbq %rcx, %rax
movq 280(%rsi), %rdx
movq 280(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 272(%rdi)
sbbq %rdx, %rcx
movq 288(%rsi), %rax
movq 288(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 280(%rdi)
sbbq %rax, %rdx
movq 296(%rsi), %rcx
movq 296(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 288(%rdi)
sbbq %rcx, %rax
movq 304(%rsi), %rdx
movq 304(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 296(%rdi)
sbbq %rdx, %rcx
movq 312(%rsi), %rax
movq 312(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 304(%rdi)
sbbq %rax, %rdx
movq 320(%rsi), %rcx
movq 320(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 312(%rdi)
sbbq %rcx, %rax
movq 328(%rsi), %rdx
movq 328(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 320(%rdi)
sbbq %rdx, %rcx
movq 336(%rsi), %rax
movq 336(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 328(%rdi)
sbbq %rax, %rdx
movq 344(%rsi), %rcx
movq 344(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 336(%rdi)
sbbq %rcx, %rax
movq 352(%rsi), %rdx
movq 352(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 344(%rdi)
sbbq %rdx, %rcx
movq 360(%rsi), %rax
movq 360(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 352(%rdi)
sbbq %rax, %rdx
movq 368(%rsi), %rcx
movq 368(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 360(%rdi)
sbbq %rcx, %rax
movq 376(%rsi), %rdx
movq 376(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 368(%rdi)
sbbq %rdx, %rcx
movq %rcx, 376(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
popq %r14
popq %r13
popq %r12
@@ -27481,6 +27739,7 @@ _sp_3072_cond_add_24:
#ifndef __APPLE__
.size sp_3072_cond_add_24,.-sp_3072_cond_add_24
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -27627,6 +27886,7 @@ _sp_3072_cond_add_avx2_24:
#ifndef __APPLE__
.size sp_3072_cond_add_avx2_24,.-sp_3072_cond_add_avx2_24
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Shift number left by n bit. (r = a << n)
*
* r Result of left shift by n.
@@ -27645,155 +27905,164 @@ sp_3072_lshift_48:
.p2align 4
_sp_3072_lshift_48:
#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ movq %rdi, %r9
movb %dl, %cl
- movq $0x00, %r10
- movq 344(%rsi), %r11
- movq 352(%rsi), %rdx
- movq 360(%rsi), %rax
- movq 368(%rsi), %r8
- movq 376(%rsi), %r9
- shldq %cl, %r9, %r10
- shldq %cl, %r8, %r9
+ movq %rsi, %rdx
+ movq $0x00, %r12
+ movq 344(%rdx), %r13
+ movq 352(%rdx), %rax
+ movq 360(%rdx), %r8
+ movq 368(%rdx), %r10
+ movq 376(%rdx), %r11
+ shldq %cl, %r11, %r12
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 352(%rdi)
- movq %rax, 360(%rdi)
- movq %r8, 368(%rdi)
- movq %r9, 376(%rdi)
- movq %r10, 384(%rdi)
- movq 312(%rsi), %r9
- movq 320(%rsi), %rdx
- movq 328(%rsi), %rax
- movq 336(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 352(%r9)
+ movq %r8, 360(%r9)
+ movq %r10, 368(%r9)
+ movq %r11, 376(%r9)
+ movq %r12, 384(%r9)
+ movq 312(%rdx), %r11
+ movq 320(%rdx), %rax
+ movq 328(%rdx), %r8
+ movq 336(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 320(%rdi)
- movq %rax, 328(%rdi)
- movq %r8, 336(%rdi)
- movq %r11, 344(%rdi)
- movq 280(%rsi), %r11
- movq 288(%rsi), %rdx
- movq 296(%rsi), %rax
- movq 304(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 320(%r9)
+ movq %r8, 328(%r9)
+ movq %r10, 336(%r9)
+ movq %r13, 344(%r9)
+ movq 280(%rdx), %r13
+ movq 288(%rdx), %rax
+ movq 296(%rdx), %r8
+ movq 304(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 288(%rdi)
- movq %rax, 296(%rdi)
- movq %r8, 304(%rdi)
- movq %r9, 312(%rdi)
- movq 248(%rsi), %r9
- movq 256(%rsi), %rdx
- movq 264(%rsi), %rax
- movq 272(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 288(%r9)
+ movq %r8, 296(%r9)
+ movq %r10, 304(%r9)
+ movq %r11, 312(%r9)
+ movq 248(%rdx), %r11
+ movq 256(%rdx), %rax
+ movq 264(%rdx), %r8
+ movq 272(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 256(%rdi)
- movq %rax, 264(%rdi)
- movq %r8, 272(%rdi)
- movq %r11, 280(%rdi)
- movq 216(%rsi), %r11
- movq 224(%rsi), %rdx
- movq 232(%rsi), %rax
- movq 240(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 256(%r9)
+ movq %r8, 264(%r9)
+ movq %r10, 272(%r9)
+ movq %r13, 280(%r9)
+ movq 216(%rdx), %r13
+ movq 224(%rdx), %rax
+ movq 232(%rdx), %r8
+ movq 240(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 224(%rdi)
- movq %rax, 232(%rdi)
- movq %r8, 240(%rdi)
- movq %r9, 248(%rdi)
- movq 184(%rsi), %r9
- movq 192(%rsi), %rdx
- movq 200(%rsi), %rax
- movq 208(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 224(%r9)
+ movq %r8, 232(%r9)
+ movq %r10, 240(%r9)
+ movq %r11, 248(%r9)
+ movq 184(%rdx), %r11
+ movq 192(%rdx), %rax
+ movq 200(%rdx), %r8
+ movq 208(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 192(%rdi)
- movq %rax, 200(%rdi)
- movq %r8, 208(%rdi)
- movq %r11, 216(%rdi)
- movq 152(%rsi), %r11
- movq 160(%rsi), %rdx
- movq 168(%rsi), %rax
- movq 176(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 192(%r9)
+ movq %r8, 200(%r9)
+ movq %r10, 208(%r9)
+ movq %r13, 216(%r9)
+ movq 152(%rdx), %r13
+ movq 160(%rdx), %rax
+ movq 168(%rdx), %r8
+ movq 176(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 160(%rdi)
- movq %rax, 168(%rdi)
- movq %r8, 176(%rdi)
- movq %r9, 184(%rdi)
- movq 120(%rsi), %r9
- movq 128(%rsi), %rdx
- movq 136(%rsi), %rax
- movq 144(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 160(%r9)
+ movq %r8, 168(%r9)
+ movq %r10, 176(%r9)
+ movq %r11, 184(%r9)
+ movq 120(%rdx), %r11
+ movq 128(%rdx), %rax
+ movq 136(%rdx), %r8
+ movq 144(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 128(%rdi)
- movq %rax, 136(%rdi)
- movq %r8, 144(%rdi)
- movq %r11, 152(%rdi)
- movq 88(%rsi), %r11
- movq 96(%rsi), %rdx
- movq 104(%rsi), %rax
- movq 112(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 128(%r9)
+ movq %r8, 136(%r9)
+ movq %r10, 144(%r9)
+ movq %r13, 152(%r9)
+ movq 88(%rdx), %r13
+ movq 96(%rdx), %rax
+ movq 104(%rdx), %r8
+ movq 112(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 96(%rdi)
- movq %rax, 104(%rdi)
- movq %r8, 112(%rdi)
- movq %r9, 120(%rdi)
- movq 56(%rsi), %r9
- movq 64(%rsi), %rdx
- movq 72(%rsi), %rax
- movq 80(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 96(%r9)
+ movq %r8, 104(%r9)
+ movq %r10, 112(%r9)
+ movq %r11, 120(%r9)
+ movq 56(%rdx), %r11
+ movq 64(%rdx), %rax
+ movq 72(%rdx), %r8
+ movq 80(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 64(%rdi)
- movq %rax, 72(%rdi)
- movq %r8, 80(%rdi)
- movq %r11, 88(%rdi)
- movq 24(%rsi), %r11
- movq 32(%rsi), %rdx
- movq 40(%rsi), %rax
- movq 48(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 64(%r9)
+ movq %r8, 72(%r9)
+ movq %r10, 80(%r9)
+ movq %r13, 88(%r9)
+ movq 24(%rdx), %r13
+ movq 32(%rdx), %rax
+ movq 40(%rdx), %r8
+ movq 48(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 32(%rdi)
- movq %rax, 40(%rdi)
- movq %r8, 48(%rdi)
- movq %r9, 56(%rdi)
- movq (%rsi), %rdx
- movq 8(%rsi), %rax
- movq 16(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 32(%r9)
+ movq %r8, 40(%r9)
+ movq %r10, 48(%r9)
+ movq %r11, 56(%r9)
+ movq (%rdx), %rax
+ movq 8(%rdx), %r8
+ movq 16(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shlq %cl, %rdx
- movq %rdx, (%rdi)
- movq %rax, 8(%rdi)
- movq %r8, 16(%rdi)
- movq %r11, 24(%rdi)
+ shlq %cl, %rax
+ movq %rax, (%r9)
+ movq %r8, 8(%r9)
+ movq %r10, 16(%r9)
+ movq %r13, 24(%r9)
+ popq %r13
+ popq %r12
repz retq
+#ifndef __APPLE__
+.size sp_3072_lshift_48,.-sp_3072_lshift_48
+#endif /* __APPLE__ */
#endif /* !WOLFSSL_SP_NO_3072 */
#endif /* !WOLFSSL_SP_NO_3072 */
#ifdef WOLFSSL_SP_4096
@@ -27892,6 +28161,7 @@ L_4096_from_bin_bswap_zero_end:
#ifndef __APPLE__
.size sp_4096_from_bin_bswap,.-sp_4096_from_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Read big endian unsigned byte array into r.
* Uses the movbe instruction which is an optional instruction.
*
@@ -27977,6 +28247,7 @@ L_4096_from_bin_movbe_zero_end:
#ifndef __APPLE__
.size sp_4096_from_bin_movbe,.-sp_4096_from_bin_movbe
#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 512
* Uses the bswap instruction.
@@ -28192,6 +28463,7 @@ _sp_4096_to_bin_bswap:
#ifndef __APPLE__
.size sp_4096_to_bin_bswap,.-sp_4096_to_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 512
* Uses the movbe instruction which is optional.
@@ -28343,6 +28615,7 @@ _sp_4096_to_bin_movbe:
#ifndef __APPLE__
.size sp_4096_to_bin_movbe,.-sp_4096_to_bin_movbe
#endif /* __APPLE__ */
+#endif /* NO_MOVBE_SUPPORT */
/* Sub b from a into a. (a -= b)
*
* a A single precision integer and result.
@@ -29031,6 +29304,11 @@ _sp_4096_mul_64:
#else
callq _sp_2048_mul_32
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1552(%rsp), %rdx
+ movq 1544(%rsp), %rsi
+ movq 1536(%rsp), %rdi
+#endif /* _WIN64 */
movq 1560(%rsp), %r13
movq 1568(%rsp), %r14
movq 1536(%rsp), %r15
@@ -30383,6 +30661,10 @@ _sp_4096_sqr_64:
#else
callq _sp_2048_sqr_32
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1288(%rsp), %rsi
+ movq 1280(%rsp), %rdi
+#endif /* _WIN64 */
movq 1296(%rsp), %r10
leaq 1024(%rsp), %r8
movq %r10, %rcx
@@ -31364,6 +31646,7 @@ _sp_4096_sqr_64:
#ifndef __APPLE__
.size sp_4096_sqr_64,.-sp_4096_sqr_64
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -31620,6 +31903,11 @@ _sp_4096_mul_avx2_64:
#else
callq _sp_2048_mul_avx2_32
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1552(%rsp), %rdx
+ movq 1544(%rsp), %rsi
+ movq 1536(%rsp), %rdi
+#endif /* _WIN64 */
movq 1560(%rsp), %r13
movq 1568(%rsp), %r14
movq 1536(%rsp), %r15
@@ -32613,6 +32901,8 @@ _sp_4096_mul_avx2_64:
#ifndef __APPLE__
.size sp_4096_mul_avx2_64,.-sp_4096_mul_avx2_64
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square a and put result in r. (r = a * a)
*
* r A single precision integer.
@@ -32757,6 +33047,10 @@ _sp_4096_sqr_avx2_64:
#else
callq _sp_2048_sqr_avx2_32
#endif /* __APPLE__ */
+#ifdef _WIN64
+ movq 1288(%rsp), %rsi
+ movq 1280(%rsp), %rdi
+#endif /* _WIN64 */
movq 1296(%rsp), %r10
leaq 1024(%rsp), %r8
movq %r10, %rcx
@@ -33674,6 +33968,7 @@ _sp_4096_sqr_avx2_64:
#ifndef __APPLE__
.size sp_4096_sqr_avx2_64,.-sp_4096_sqr_avx2_64
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -34711,7 +35006,7 @@ _sp_4096_mont_reduce_64:
movq $0x40, %r8
movq (%rdi), %r13
movq 8(%rdi), %r14
-L_mont_loop_64:
+L_4096_mont_loop_64:
# mu = a[i] * mp
movq %r13, %r11
imulq %rcx, %r11
@@ -35354,12 +35649,17 @@ L_mont_loop_64:
# i -= 1
addq $8, %rdi
decq %r8
- jnz L_mont_loop_64
+ jnz L_4096_mont_loop_64
movq %r13, (%rdi)
movq %r14, 8(%rdi)
negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
movq %r15, %rcx
movq %rsi, %rdx
+#endif /* _WIN64 */
movq %rdi, %rsi
movq %rdi, %rdi
subq $0x200, %rdi
@@ -35376,6 +35676,7 @@ L_mont_loop_64:
#ifndef __APPLE__
.size sp_4096_mont_reduce_64,.-sp_4096_mont_reduce_64
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally subtract b from a using the mask m.
* m is -1 to subtract and 0 when not copying.
*
@@ -35722,6 +36023,7 @@ _sp_4096_cond_sub_avx2_64:
#ifndef __APPLE__
.size sp_4096_cond_sub_avx2_64,.-sp_4096_cond_sub_avx2_64
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifdef HAVE_INTEL_AVX2
/* Mul a by digit b into r. (r = a * b)
*
@@ -35751,374 +36053,374 @@ _sp_4096_mul_d_avx2_64:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 40(%rdi)
adoxq %r8, %r9
+ movq %r10, 40(%rdi)
# A[6] * B
mulxq 48(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 48(%rdi)
adoxq %r8, %r10
+ movq %r9, 48(%rdi)
# A[7] * B
mulxq 56(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 56(%rdi)
adoxq %r8, %r9
+ movq %r10, 56(%rdi)
# A[8] * B
mulxq 64(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 64(%rdi)
adoxq %r8, %r10
+ movq %r9, 64(%rdi)
# A[9] * B
mulxq 72(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 72(%rdi)
adoxq %r8, %r9
+ movq %r10, 72(%rdi)
# A[10] * B
mulxq 80(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 80(%rdi)
adoxq %r8, %r10
+ movq %r9, 80(%rdi)
# A[11] * B
mulxq 88(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 88(%rdi)
adoxq %r8, %r9
+ movq %r10, 88(%rdi)
# A[12] * B
mulxq 96(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 96(%rdi)
adoxq %r8, %r10
+ movq %r9, 96(%rdi)
# A[13] * B
mulxq 104(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 104(%rdi)
adoxq %r8, %r9
+ movq %r10, 104(%rdi)
# A[14] * B
mulxq 112(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 112(%rdi)
adoxq %r8, %r10
+ movq %r9, 112(%rdi)
# A[15] * B
mulxq 120(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 120(%rdi)
adoxq %r8, %r9
+ movq %r10, 120(%rdi)
# A[16] * B
mulxq 128(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 128(%rdi)
adoxq %r8, %r10
+ movq %r9, 128(%rdi)
# A[17] * B
mulxq 136(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 136(%rdi)
adoxq %r8, %r9
+ movq %r10, 136(%rdi)
# A[18] * B
mulxq 144(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 144(%rdi)
adoxq %r8, %r10
+ movq %r9, 144(%rdi)
# A[19] * B
mulxq 152(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 152(%rdi)
adoxq %r8, %r9
+ movq %r10, 152(%rdi)
# A[20] * B
mulxq 160(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 160(%rdi)
adoxq %r8, %r10
+ movq %r9, 160(%rdi)
# A[21] * B
mulxq 168(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 168(%rdi)
adoxq %r8, %r9
+ movq %r10, 168(%rdi)
# A[22] * B
mulxq 176(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 176(%rdi)
adoxq %r8, %r10
+ movq %r9, 176(%rdi)
# A[23] * B
mulxq 184(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 184(%rdi)
adoxq %r8, %r9
+ movq %r10, 184(%rdi)
# A[24] * B
mulxq 192(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 192(%rdi)
adoxq %r8, %r10
+ movq %r9, 192(%rdi)
# A[25] * B
mulxq 200(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 200(%rdi)
adoxq %r8, %r9
+ movq %r10, 200(%rdi)
# A[26] * B
mulxq 208(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 208(%rdi)
adoxq %r8, %r10
+ movq %r9, 208(%rdi)
# A[27] * B
mulxq 216(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 216(%rdi)
adoxq %r8, %r9
+ movq %r10, 216(%rdi)
# A[28] * B
mulxq 224(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 224(%rdi)
adoxq %r8, %r10
+ movq %r9, 224(%rdi)
# A[29] * B
mulxq 232(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 232(%rdi)
adoxq %r8, %r9
+ movq %r10, 232(%rdi)
# A[30] * B
mulxq 240(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 240(%rdi)
adoxq %r8, %r10
+ movq %r9, 240(%rdi)
# A[31] * B
mulxq 248(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 248(%rdi)
adoxq %r8, %r9
+ movq %r10, 248(%rdi)
# A[32] * B
mulxq 256(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 256(%rdi)
adoxq %r8, %r10
+ movq %r9, 256(%rdi)
# A[33] * B
mulxq 264(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 264(%rdi)
adoxq %r8, %r9
+ movq %r10, 264(%rdi)
# A[34] * B
mulxq 272(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 272(%rdi)
adoxq %r8, %r10
+ movq %r9, 272(%rdi)
# A[35] * B
mulxq 280(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 280(%rdi)
adoxq %r8, %r9
+ movq %r10, 280(%rdi)
# A[36] * B
mulxq 288(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 288(%rdi)
adoxq %r8, %r10
+ movq %r9, 288(%rdi)
# A[37] * B
mulxq 296(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 296(%rdi)
adoxq %r8, %r9
+ movq %r10, 296(%rdi)
# A[38] * B
mulxq 304(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 304(%rdi)
adoxq %r8, %r10
+ movq %r9, 304(%rdi)
# A[39] * B
mulxq 312(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 312(%rdi)
adoxq %r8, %r9
+ movq %r10, 312(%rdi)
# A[40] * B
mulxq 320(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 320(%rdi)
adoxq %r8, %r10
+ movq %r9, 320(%rdi)
# A[41] * B
mulxq 328(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 328(%rdi)
adoxq %r8, %r9
+ movq %r10, 328(%rdi)
# A[42] * B
mulxq 336(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 336(%rdi)
adoxq %r8, %r10
+ movq %r9, 336(%rdi)
# A[43] * B
mulxq 344(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 344(%rdi)
adoxq %r8, %r9
+ movq %r10, 344(%rdi)
# A[44] * B
mulxq 352(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 352(%rdi)
adoxq %r8, %r10
+ movq %r9, 352(%rdi)
# A[45] * B
mulxq 360(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 360(%rdi)
adoxq %r8, %r9
+ movq %r10, 360(%rdi)
# A[46] * B
mulxq 368(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 368(%rdi)
adoxq %r8, %r10
+ movq %r9, 368(%rdi)
# A[47] * B
mulxq 376(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 376(%rdi)
adoxq %r8, %r9
+ movq %r10, 376(%rdi)
# A[48] * B
mulxq 384(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 384(%rdi)
adoxq %r8, %r10
+ movq %r9, 384(%rdi)
# A[49] * B
mulxq 392(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 392(%rdi)
adoxq %r8, %r9
+ movq %r10, 392(%rdi)
# A[50] * B
mulxq 400(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 400(%rdi)
adoxq %r8, %r10
+ movq %r9, 400(%rdi)
# A[51] * B
mulxq 408(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 408(%rdi)
adoxq %r8, %r9
+ movq %r10, 408(%rdi)
# A[52] * B
mulxq 416(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 416(%rdi)
adoxq %r8, %r10
+ movq %r9, 416(%rdi)
# A[53] * B
mulxq 424(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 424(%rdi)
adoxq %r8, %r9
+ movq %r10, 424(%rdi)
# A[54] * B
mulxq 432(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 432(%rdi)
adoxq %r8, %r10
+ movq %r9, 432(%rdi)
# A[55] * B
mulxq 440(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 440(%rdi)
adoxq %r8, %r9
+ movq %r10, 440(%rdi)
# A[56] * B
mulxq 448(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 448(%rdi)
adoxq %r8, %r10
+ movq %r9, 448(%rdi)
# A[57] * B
mulxq 456(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 456(%rdi)
adoxq %r8, %r9
+ movq %r10, 456(%rdi)
# A[58] * B
mulxq 464(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 464(%rdi)
adoxq %r8, %r10
+ movq %r9, 464(%rdi)
# A[59] * B
mulxq 472(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 472(%rdi)
adoxq %r8, %r9
+ movq %r10, 472(%rdi)
# A[60] * B
mulxq 480(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 480(%rdi)
adoxq %r8, %r10
+ movq %r9, 480(%rdi)
# A[61] * B
mulxq 488(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 488(%rdi)
adoxq %r8, %r9
+ movq %r10, 488(%rdi)
# A[62] * B
mulxq 496(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 496(%rdi)
adoxq %r8, %r10
+ movq %r9, 496(%rdi)
# A[63] * B
mulxq 504(%rsi), %rcx, %r8
movq %r11, %r9
@@ -36132,6 +36434,35 @@ _sp_4096_mul_d_avx2_64:
.size sp_4096_mul_d_avx2_64,.-sp_4096_mul_d_avx2_64
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_4096_word_asm_64
+.type div_4096_word_asm_64,@function
+.align 16
+div_4096_word_asm_64:
+#else
+.section __TEXT,__text
+.globl _div_4096_word_asm_64
+.p2align 4
+_div_4096_word_asm_64:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_4096_word_asm_64,.-div_4096_word_asm_64
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -36910,14 +37241,20 @@ _sp_4096_mont_reduce_avx2_64:
pushq %r12
pushq %r13
pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
movq %rdx, %r8
- xorq %r14, %r14
+ xorq %rbp, %rbp
# i = 64
movq $0x40, %r9
movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
addq $0x100, %rdi
- xorq %r12, %r12
-L_mont_loop_avx2_64:
+ xorq %rbp, %rbp
+L_4096_mont_loop_avx2_64:
# mu = a[i] * mp
movq %r13, %rdx
movq %r13, %r10
@@ -36925,32 +37262,29 @@ L_mont_loop_avx2_64:
xorq %r12, %r12
# a[i+0] += m[0] * mu
mulxq (%rsi), %rax, %rcx
- movq -248(%rdi), %r13
+ movq %r14, %r13
adcxq %rax, %r10
adoxq %rcx, %r13
# a[i+1] += m[1] * mu
mulxq 8(%rsi), %rax, %rcx
- movq -240(%rdi), %r10
+ movq %r15, %r14
adcxq %rax, %r13
- adoxq %rcx, %r10
+ adoxq %rcx, %r14
# a[i+2] += m[2] * mu
mulxq 16(%rsi), %rax, %rcx
- movq -232(%rdi), %r11
- adcxq %rax, %r10
- adoxq %rcx, %r11
- movq %r10, -240(%rdi)
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
# a[i+3] += m[3] * mu
mulxq 24(%rsi), %rax, %rcx
- movq -224(%rdi), %r10
- adcxq %rax, %r11
- adoxq %rcx, %r10
- movq %r11, -232(%rdi)
+ movq -224(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
# a[i+4] += m[4] * mu
mulxq 32(%rsi), %rax, %rcx
movq -216(%rdi), %r11
- adcxq %rax, %r10
+ adcxq %rax, %rbx
adoxq %rcx, %r11
- movq %r10, -224(%rdi)
# a[i+5] += m[5] * mu
mulxq 40(%rsi), %rax, %rcx
movq -208(%rdi), %r10
@@ -37305,340 +37639,343 @@ L_mont_loop_avx2_64:
adcxq %rax, %r11
adoxq %rcx, %r10
movq %r11, 248(%rdi)
- adcxq %r14, %r10
+ adcxq %rbp, %r10
+ movq %r12, %rbp
movq %r10, 256(%rdi)
- movq %r12, %r14
- adoxq %r12, %r14
- adcxq %r12, %r14
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
# a += 1
addq $8, %rdi
# i -= 1
subq $0x01, %r9
- jnz L_mont_loop_avx2_64
+ jnz L_4096_mont_loop_avx2_64
subq $0x100, %rdi
- negq %r14
+ negq %rbp
movq %rdi, %r8
subq $0x200, %rdi
movq (%rsi), %rcx
movq %r13, %rdx
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
subq %rcx, %rdx
movq 8(%rsi), %rcx
- movq 8(%r8), %rax
- pextq %r14, %rcx, %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
movq %rdx, (%rdi)
sbbq %rcx, %rax
movq 16(%rsi), %rdx
- movq 16(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
movq %rax, 8(%rdi)
sbbq %rdx, %rcx
movq 24(%rsi), %rax
- movq 24(%r8), %rdx
- pextq %r14, %rax, %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
movq %rcx, 16(%rdi)
sbbq %rax, %rdx
movq 32(%rsi), %rcx
movq 32(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 24(%rdi)
sbbq %rcx, %rax
movq 40(%rsi), %rdx
movq 40(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 32(%rdi)
sbbq %rdx, %rcx
movq 48(%rsi), %rax
movq 48(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 40(%rdi)
sbbq %rax, %rdx
movq 56(%rsi), %rcx
movq 56(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 48(%rdi)
sbbq %rcx, %rax
movq 64(%rsi), %rdx
movq 64(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 56(%rdi)
sbbq %rdx, %rcx
movq 72(%rsi), %rax
movq 72(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 64(%rdi)
sbbq %rax, %rdx
movq 80(%rsi), %rcx
movq 80(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 72(%rdi)
sbbq %rcx, %rax
movq 88(%rsi), %rdx
movq 88(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 80(%rdi)
sbbq %rdx, %rcx
movq 96(%rsi), %rax
movq 96(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 88(%rdi)
sbbq %rax, %rdx
movq 104(%rsi), %rcx
movq 104(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 96(%rdi)
sbbq %rcx, %rax
movq 112(%rsi), %rdx
movq 112(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 104(%rdi)
sbbq %rdx, %rcx
movq 120(%rsi), %rax
movq 120(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 112(%rdi)
sbbq %rax, %rdx
movq 128(%rsi), %rcx
movq 128(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 120(%rdi)
sbbq %rcx, %rax
movq 136(%rsi), %rdx
movq 136(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 128(%rdi)
sbbq %rdx, %rcx
movq 144(%rsi), %rax
movq 144(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 136(%rdi)
sbbq %rax, %rdx
movq 152(%rsi), %rcx
movq 152(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 144(%rdi)
sbbq %rcx, %rax
movq 160(%rsi), %rdx
movq 160(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 152(%rdi)
sbbq %rdx, %rcx
movq 168(%rsi), %rax
movq 168(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 160(%rdi)
sbbq %rax, %rdx
movq 176(%rsi), %rcx
movq 176(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 168(%rdi)
sbbq %rcx, %rax
movq 184(%rsi), %rdx
movq 184(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 176(%rdi)
sbbq %rdx, %rcx
movq 192(%rsi), %rax
movq 192(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 184(%rdi)
sbbq %rax, %rdx
movq 200(%rsi), %rcx
movq 200(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 192(%rdi)
sbbq %rcx, %rax
movq 208(%rsi), %rdx
movq 208(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 200(%rdi)
sbbq %rdx, %rcx
movq 216(%rsi), %rax
movq 216(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 208(%rdi)
sbbq %rax, %rdx
movq 224(%rsi), %rcx
movq 224(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 216(%rdi)
sbbq %rcx, %rax
movq 232(%rsi), %rdx
movq 232(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 224(%rdi)
sbbq %rdx, %rcx
movq 240(%rsi), %rax
movq 240(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 232(%rdi)
sbbq %rax, %rdx
movq 248(%rsi), %rcx
movq 248(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 240(%rdi)
sbbq %rcx, %rax
movq 256(%rsi), %rdx
movq 256(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 248(%rdi)
sbbq %rdx, %rcx
movq 264(%rsi), %rax
movq 264(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 256(%rdi)
sbbq %rax, %rdx
movq 272(%rsi), %rcx
movq 272(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 264(%rdi)
sbbq %rcx, %rax
movq 280(%rsi), %rdx
movq 280(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 272(%rdi)
sbbq %rdx, %rcx
movq 288(%rsi), %rax
movq 288(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 280(%rdi)
sbbq %rax, %rdx
movq 296(%rsi), %rcx
movq 296(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 288(%rdi)
sbbq %rcx, %rax
movq 304(%rsi), %rdx
movq 304(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 296(%rdi)
sbbq %rdx, %rcx
movq 312(%rsi), %rax
movq 312(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 304(%rdi)
sbbq %rax, %rdx
movq 320(%rsi), %rcx
movq 320(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 312(%rdi)
sbbq %rcx, %rax
movq 328(%rsi), %rdx
movq 328(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 320(%rdi)
sbbq %rdx, %rcx
movq 336(%rsi), %rax
movq 336(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 328(%rdi)
sbbq %rax, %rdx
movq 344(%rsi), %rcx
movq 344(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 336(%rdi)
sbbq %rcx, %rax
movq 352(%rsi), %rdx
movq 352(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 344(%rdi)
sbbq %rdx, %rcx
movq 360(%rsi), %rax
movq 360(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 352(%rdi)
sbbq %rax, %rdx
movq 368(%rsi), %rcx
movq 368(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 360(%rdi)
sbbq %rcx, %rax
movq 376(%rsi), %rdx
movq 376(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 368(%rdi)
sbbq %rdx, %rcx
movq 384(%rsi), %rax
movq 384(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 376(%rdi)
sbbq %rax, %rdx
movq 392(%rsi), %rcx
movq 392(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 384(%rdi)
sbbq %rcx, %rax
movq 400(%rsi), %rdx
movq 400(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 392(%rdi)
sbbq %rdx, %rcx
movq 408(%rsi), %rax
movq 408(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 400(%rdi)
sbbq %rax, %rdx
movq 416(%rsi), %rcx
movq 416(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 408(%rdi)
sbbq %rcx, %rax
movq 424(%rsi), %rdx
movq 424(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 416(%rdi)
sbbq %rdx, %rcx
movq 432(%rsi), %rax
movq 432(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 424(%rdi)
sbbq %rax, %rdx
movq 440(%rsi), %rcx
movq 440(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 432(%rdi)
sbbq %rcx, %rax
movq 448(%rsi), %rdx
movq 448(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 440(%rdi)
sbbq %rdx, %rcx
movq 456(%rsi), %rax
movq 456(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 448(%rdi)
sbbq %rax, %rdx
movq 464(%rsi), %rcx
movq 464(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 456(%rdi)
sbbq %rcx, %rax
movq 472(%rsi), %rdx
movq 472(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 464(%rdi)
sbbq %rdx, %rcx
movq 480(%rsi), %rax
movq 480(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 472(%rdi)
sbbq %rax, %rdx
movq 488(%rsi), %rcx
movq 488(%r8), %rax
- pextq %r14, %rcx, %rcx
+ pextq %rbp, %rcx, %rcx
movq %rdx, 480(%rdi)
sbbq %rcx, %rax
movq 496(%rsi), %rdx
movq 496(%r8), %rcx
- pextq %r14, %rdx, %rdx
+ pextq %rbp, %rdx, %rdx
movq %rax, 488(%rdi)
sbbq %rdx, %rcx
movq 504(%rsi), %rax
movq 504(%r8), %rdx
- pextq %r14, %rax, %rax
+ pextq %rbp, %rax, %rax
movq %rcx, 496(%rdi)
sbbq %rax, %rdx
movq %rdx, 504(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
popq %r14
popq %r13
popq %r12
@@ -37899,6 +38236,7 @@ _sp_4096_cond_add_32:
#ifndef __APPLE__
.size sp_4096_cond_add_32,.-sp_4096_cond_add_32
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -38085,6 +38423,7 @@ _sp_4096_cond_add_avx2_32:
#ifndef __APPLE__
.size sp_4096_cond_add_avx2_32,.-sp_4096_cond_add_avx2_32
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Shift number left by n bit. (r = a << n)
*
* r Result of left shift by n.
@@ -38103,206 +38442,550 @@ sp_4096_lshift_64:
.p2align 4
_sp_4096_lshift_64:
#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ movq %rdi, %r9
movb %dl, %cl
- movq $0x00, %r10
- movq 472(%rsi), %r11
- movq 480(%rsi), %rdx
- movq 488(%rsi), %rax
- movq 496(%rsi), %r8
- movq 504(%rsi), %r9
- shldq %cl, %r9, %r10
- shldq %cl, %r8, %r9
+ movq %rsi, %rdx
+ movq $0x00, %r12
+ movq 472(%rdx), %r13
+ movq 480(%rdx), %rax
+ movq 488(%rdx), %r8
+ movq 496(%rdx), %r10
+ movq 504(%rdx), %r11
+ shldq %cl, %r11, %r12
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 480(%rdi)
- movq %rax, 488(%rdi)
- movq %r8, 496(%rdi)
- movq %r9, 504(%rdi)
- movq %r10, 512(%rdi)
- movq 440(%rsi), %r9
- movq 448(%rsi), %rdx
- movq 456(%rsi), %rax
- movq 464(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 480(%r9)
+ movq %r8, 488(%r9)
+ movq %r10, 496(%r9)
+ movq %r11, 504(%r9)
+ movq %r12, 512(%r9)
+ movq 440(%rdx), %r11
+ movq 448(%rdx), %rax
+ movq 456(%rdx), %r8
+ movq 464(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 448(%rdi)
- movq %rax, 456(%rdi)
- movq %r8, 464(%rdi)
- movq %r11, 472(%rdi)
- movq 408(%rsi), %r11
- movq 416(%rsi), %rdx
- movq 424(%rsi), %rax
- movq 432(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 448(%r9)
+ movq %r8, 456(%r9)
+ movq %r10, 464(%r9)
+ movq %r13, 472(%r9)
+ movq 408(%rdx), %r13
+ movq 416(%rdx), %rax
+ movq 424(%rdx), %r8
+ movq 432(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 416(%rdi)
- movq %rax, 424(%rdi)
- movq %r8, 432(%rdi)
- movq %r9, 440(%rdi)
- movq 376(%rsi), %r9
- movq 384(%rsi), %rdx
- movq 392(%rsi), %rax
- movq 400(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 416(%r9)
+ movq %r8, 424(%r9)
+ movq %r10, 432(%r9)
+ movq %r11, 440(%r9)
+ movq 376(%rdx), %r11
+ movq 384(%rdx), %rax
+ movq 392(%rdx), %r8
+ movq 400(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 384(%rdi)
- movq %rax, 392(%rdi)
- movq %r8, 400(%rdi)
- movq %r11, 408(%rdi)
- movq 344(%rsi), %r11
- movq 352(%rsi), %rdx
- movq 360(%rsi), %rax
- movq 368(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 384(%r9)
+ movq %r8, 392(%r9)
+ movq %r10, 400(%r9)
+ movq %r13, 408(%r9)
+ movq 344(%rdx), %r13
+ movq 352(%rdx), %rax
+ movq 360(%rdx), %r8
+ movq 368(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 352(%rdi)
- movq %rax, 360(%rdi)
- movq %r8, 368(%rdi)
- movq %r9, 376(%rdi)
- movq 312(%rsi), %r9
- movq 320(%rsi), %rdx
- movq 328(%rsi), %rax
- movq 336(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 352(%r9)
+ movq %r8, 360(%r9)
+ movq %r10, 368(%r9)
+ movq %r11, 376(%r9)
+ movq 312(%rdx), %r11
+ movq 320(%rdx), %rax
+ movq 328(%rdx), %r8
+ movq 336(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 320(%rdi)
- movq %rax, 328(%rdi)
- movq %r8, 336(%rdi)
- movq %r11, 344(%rdi)
- movq 280(%rsi), %r11
- movq 288(%rsi), %rdx
- movq 296(%rsi), %rax
- movq 304(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 320(%r9)
+ movq %r8, 328(%r9)
+ movq %r10, 336(%r9)
+ movq %r13, 344(%r9)
+ movq 280(%rdx), %r13
+ movq 288(%rdx), %rax
+ movq 296(%rdx), %r8
+ movq 304(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 288(%rdi)
- movq %rax, 296(%rdi)
- movq %r8, 304(%rdi)
- movq %r9, 312(%rdi)
- movq 248(%rsi), %r9
- movq 256(%rsi), %rdx
- movq 264(%rsi), %rax
- movq 272(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 288(%r9)
+ movq %r8, 296(%r9)
+ movq %r10, 304(%r9)
+ movq %r11, 312(%r9)
+ movq 248(%rdx), %r11
+ movq 256(%rdx), %rax
+ movq 264(%rdx), %r8
+ movq 272(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 256(%rdi)
- movq %rax, 264(%rdi)
- movq %r8, 272(%rdi)
- movq %r11, 280(%rdi)
- movq 216(%rsi), %r11
- movq 224(%rsi), %rdx
- movq 232(%rsi), %rax
- movq 240(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 256(%r9)
+ movq %r8, 264(%r9)
+ movq %r10, 272(%r9)
+ movq %r13, 280(%r9)
+ movq 216(%rdx), %r13
+ movq 224(%rdx), %rax
+ movq 232(%rdx), %r8
+ movq 240(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 224(%rdi)
- movq %rax, 232(%rdi)
- movq %r8, 240(%rdi)
- movq %r9, 248(%rdi)
- movq 184(%rsi), %r9
- movq 192(%rsi), %rdx
- movq 200(%rsi), %rax
- movq 208(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 224(%r9)
+ movq %r8, 232(%r9)
+ movq %r10, 240(%r9)
+ movq %r11, 248(%r9)
+ movq 184(%rdx), %r11
+ movq 192(%rdx), %rax
+ movq 200(%rdx), %r8
+ movq 208(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 192(%rdi)
- movq %rax, 200(%rdi)
- movq %r8, 208(%rdi)
- movq %r11, 216(%rdi)
- movq 152(%rsi), %r11
- movq 160(%rsi), %rdx
- movq 168(%rsi), %rax
- movq 176(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 192(%r9)
+ movq %r8, 200(%r9)
+ movq %r10, 208(%r9)
+ movq %r13, 216(%r9)
+ movq 152(%rdx), %r13
+ movq 160(%rdx), %rax
+ movq 168(%rdx), %r8
+ movq 176(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 160(%rdi)
- movq %rax, 168(%rdi)
- movq %r8, 176(%rdi)
- movq %r9, 184(%rdi)
- movq 120(%rsi), %r9
- movq 128(%rsi), %rdx
- movq 136(%rsi), %rax
- movq 144(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 160(%r9)
+ movq %r8, 168(%r9)
+ movq %r10, 176(%r9)
+ movq %r11, 184(%r9)
+ movq 120(%rdx), %r11
+ movq 128(%rdx), %rax
+ movq 136(%rdx), %r8
+ movq 144(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 128(%rdi)
- movq %rax, 136(%rdi)
- movq %r8, 144(%rdi)
- movq %r11, 152(%rdi)
- movq 88(%rsi), %r11
- movq 96(%rsi), %rdx
- movq 104(%rsi), %rax
- movq 112(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 128(%r9)
+ movq %r8, 136(%r9)
+ movq %r10, 144(%r9)
+ movq %r13, 152(%r9)
+ movq 88(%rdx), %r13
+ movq 96(%rdx), %rax
+ movq 104(%rdx), %r8
+ movq 112(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 96(%rdi)
- movq %rax, 104(%rdi)
- movq %r8, 112(%rdi)
- movq %r9, 120(%rdi)
- movq 56(%rsi), %r9
- movq 64(%rsi), %rdx
- movq 72(%rsi), %rax
- movq 80(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 96(%r9)
+ movq %r8, 104(%r9)
+ movq %r10, 112(%r9)
+ movq %r11, 120(%r9)
+ movq 56(%rdx), %r11
+ movq 64(%rdx), %rax
+ movq 72(%rdx), %r8
+ movq 80(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r9, %rdx
- movq %rdx, 64(%rdi)
- movq %rax, 72(%rdi)
- movq %r8, 80(%rdi)
- movq %r11, 88(%rdi)
- movq 24(%rsi), %r11
- movq 32(%rsi), %rdx
- movq 40(%rsi), %rax
- movq 48(%rsi), %r8
- shldq %cl, %r8, %r9
+ shldq %cl, %r11, %rax
+ movq %rax, 64(%r9)
+ movq %r8, 72(%r9)
+ movq %r10, 80(%r9)
+ movq %r13, 88(%r9)
+ movq 24(%rdx), %r13
+ movq 32(%rdx), %rax
+ movq 40(%rdx), %r8
+ movq 48(%rdx), %r10
+ shldq %cl, %r10, %r11
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shldq %cl, %r11, %rdx
- movq %rdx, 32(%rdi)
- movq %rax, 40(%rdi)
- movq %r8, 48(%rdi)
- movq %r9, 56(%rdi)
- movq (%rsi), %rdx
- movq 8(%rsi), %rax
- movq 16(%rsi), %r8
- shldq %cl, %r8, %r11
+ shldq %cl, %r13, %rax
+ movq %rax, 32(%r9)
+ movq %r8, 40(%r9)
+ movq %r10, 48(%r9)
+ movq %r11, 56(%r9)
+ movq (%rdx), %rax
+ movq 8(%rdx), %r8
+ movq 16(%rdx), %r10
+ shldq %cl, %r10, %r13
+ shldq %cl, %r8, %r10
shldq %cl, %rax, %r8
- shldq %cl, %rdx, %rax
- shlq %cl, %rdx
- movq %rdx, (%rdi)
- movq %rax, 8(%rdi)
- movq %r8, 16(%rdi)
- movq %r11, 24(%rdi)
+ shlq %cl, %rax
+ movq %rax, (%r9)
+ movq %r8, 8(%r9)
+ movq %r10, 16(%r9)
+ movq %r13, 24(%r9)
+ popq %r13
+ popq %r12
repz retq
+#ifndef __APPLE__
+.size sp_4096_lshift_64,.-sp_4096_lshift_64
+#endif /* __APPLE__ */
#endif /* WOLFSSL_SP_4096 */
#endif /* WOLFSSL_SP_4096 */
#ifndef WOLFSSL_SP_NO_256
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_mul_4
+.type sp_256_mul_4,@function
+.align 16
+sp_256_mul_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_mul_4
+.p2align 4
+_sp_256_mul_4:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ subq $32, %rsp
+ # A[0] * B[0]
+ movq (%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ movq %rax, (%rsp)
+ movq %rdx, %r9
+ # A[0] * B[1]
+ movq 8(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[0]
+ movq (%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 8(%rsp)
+ # A[0] * B[2]
+ movq 16(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[1]
+ movq 8(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[0]
+ movq (%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 16(%rsp)
+ # A[0] * B[3]
+ movq 24(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[2]
+ movq 16(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[1]
+ movq 8(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[0]
+ movq (%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 24(%rsp)
+ # A[1] * B[3]
+ movq 24(%rcx), %rax
+ mulq 8(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[2]
+ movq 16(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[1]
+ movq 8(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 32(%rdi)
+ # A[2] * B[3]
+ movq 24(%rcx), %rax
+ mulq 16(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[2]
+ movq 16(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 40(%rdi)
+ # A[3] * B[3]
+ movq 24(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq (%rsp), %rax
+ movq 8(%rsp), %rdx
+ movq 16(%rsp), %r8
+ movq 24(%rsp), %r9
+ movq %rax, (%rdi)
+ movq %rdx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ addq $32, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_256_mul_4,.-sp_256_mul_4
+#endif /* __APPLE__ */
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_sqr_4
+.type sp_256_sqr_4,@function
+.align 16
+sp_256_sqr_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_sqr_4
+.p2align 4
+_sp_256_sqr_4:
+#endif /* __APPLE__ */
+ pushq %r12
+ subq $32, %rsp
+ # A[0] * A[0]
+ movq (%rsi), %rax
+ mulq %rax
+ xorq %r9, %r9
+ movq %rax, (%rsp)
+ movq %rdx, %r8
+ # A[0] * A[1]
+ movq 8(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ movq %r8, 8(%rsp)
+ # A[0] * A[2]
+ movq 16(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ # A[1] * A[1]
+ movq 8(%rsi), %rax
+ mulq %rax
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ movq %r9, 16(%rsp)
+ # A[0] * A[3]
+ movq 24(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * A[2]
+ movq 16(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %rcx, 24(%rsp)
+ # A[1] * A[3]
+ movq 24(%rsi), %rax
+ mulq 8(%rsi)
+ xorq %rcx, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ # A[2] * A[2]
+ movq 16(%rsi), %rax
+ mulq %rax
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ movq %r8, 32(%rdi)
+ # A[2] * A[3]
+ movq 24(%rsi), %rax
+ mulq 16(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ movq %r9, 40(%rdi)
+ # A[3] * A[3]
+ movq 24(%rsi), %rax
+ mulq %rax
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ movq %rcx, 48(%rdi)
+ movq %r8, 56(%rdi)
+ movq (%rsp), %rax
+ movq 8(%rsp), %rdx
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq %rax, (%rdi)
+ movq %rdx, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq %r11, 24(%rdi)
+ addq $32, %rsp
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_256_sqr_4,.-sp_256_sqr_4
+#endif /* __APPLE__ */
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_add_4
+.type sp_256_add_4,@function
+.align 16
+sp_256_add_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_add_4
+.p2align 4
+_sp_256_add_4:
+#endif /* __APPLE__ */
+ # Add
+ movq (%rsi), %rcx
+ xorq %rax, %rax
+ addq (%rdx), %rcx
+ movq 8(%rsi), %r8
+ movq %rcx, (%rdi)
+ adcq 8(%rdx), %r8
+ movq 16(%rsi), %rcx
+ movq %r8, 8(%rdi)
+ adcq 16(%rdx), %rcx
+ movq 24(%rsi), %r8
+ movq %rcx, 16(%rdi)
+ adcq 24(%rdx), %r8
+ movq %r8, 24(%rdi)
+ adcq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_256_add_4,.-sp_256_add_4
+#endif /* __APPLE__ */
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_sub_4
+.type sp_256_sub_4,@function
+.align 16
+sp_256_sub_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_sub_4
+.p2align 4
+_sp_256_sub_4:
+#endif /* __APPLE__ */
+ xorq %rax, %rax
+ movq (%rsi), %rcx
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ subq (%rdx), %rcx
+ sbbq 8(%rdx), %r8
+ sbbq 16(%rdx), %r9
+ sbbq 24(%rdx), %r10
+ movq %rcx, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_256_sub_4,.-sp_256_sub_4
+#endif /* __APPLE__ */
/* Conditionally copy a into r using the mask m.
* m is -1 to copy and 0 when not.
*
@@ -38842,42 +39525,6 @@ _sp_256_cond_sub_4:
#ifndef __APPLE__
.size sp_256_cond_sub_4,.-sp_256_cond_sub_4
#endif /* __APPLE__ */
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_256_sub_4
-.type sp_256_sub_4,@function
-.align 16
-sp_256_sub_4:
-#else
-.section __TEXT,__text
-.globl _sp_256_sub_4
-.p2align 4
-_sp_256_sub_4:
-#endif /* __APPLE__ */
- xorq %rax, %rax
- movq (%rsi), %rcx
- movq 8(%rsi), %r8
- movq 16(%rsi), %r9
- movq 24(%rsi), %r10
- subq (%rdx), %rcx
- sbbq 8(%rdx), %r8
- sbbq 16(%rdx), %r9
- sbbq 24(%rdx), %r10
- movq %rcx, (%rdi)
- movq %r8, 8(%rdi)
- movq %r9, 16(%rdi)
- movq %r10, 24(%rdi)
- sbbq $0x00, %rax
- repz retq
-#ifndef __APPLE__
-.size sp_256_sub_4,.-sp_256_sub_4
-#endif /* __APPLE__ */
/* Reduce the number back to 256 bits using Montgomery reduction.
*
* a A single precision number to reduce in place.
@@ -39329,6 +39976,7 @@ L_256_get_point_33_4_start:
#ifndef __APPLE__
.size sp_256_get_point_33_4,.-sp_256_get_point_33_4
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Touch each possible point that could be being copied.
*
* r Point to copy into.
@@ -39362,9 +40010,9 @@ _sp_256_get_point_33_avx2_4:
L_256_get_point_33_avx2_4_start:
vpcmpeqd %ymm7, %ymm8, %ymm6
vpaddd %ymm9, %ymm8, %ymm8
- vmovdqu (%rsi), %ymm3
- vmovdqu 64(%rsi), %ymm4
- vmovdqu 128(%rsi), %ymm5
+ vmovupd (%rsi), %ymm3
+ vmovupd 64(%rsi), %ymm4
+ vmovupd 128(%rsi), %ymm5
addq $0xc8, %rsi
vpand %ymm6, %ymm3, %ymm3
vpand %ymm6, %ymm4, %ymm4
@@ -39374,14 +40022,16 @@ L_256_get_point_33_avx2_4_start:
vpor %ymm5, %ymm2, %ymm2
decq %rax
jnz L_256_get_point_33_avx2_4_start
- vmovdqu %ymm0, (%rdi)
- vmovdqu %ymm1, 64(%rdi)
- vmovdqu %ymm2, 128(%rdi)
+ vmovupd %ymm0, (%rdi)
+ vmovupd %ymm1, 64(%rdi)
+ vmovupd %ymm2, 128(%rdi)
repz retq
#ifndef __APPLE__
.size sp_256_get_point_33_avx2_4,.-sp_256_get_point_33_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WC_NO_CACHE_RESISTANT */
+#ifdef HAVE_INTEL_AVX2
/* Multiply two Montogmery form numbers mod the modulus (prime).
* (r = a * b mod m)
*
@@ -39404,11 +40054,11 @@ sp_256_mont_mul_avx2_4:
_sp_256_mont_mul_avx2_4:
#endif /* __APPLE__ */
pushq %rbx
- pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
+ pushq %rbp
movq %rdx, %rbp
# A[0] * B[0]
movq (%rbp), %rdx
@@ -39557,16 +40207,18 @@ _sp_256_mont_mul_avx2_4:
movq %r13, 8(%rdi)
movq %r14, 16(%rdi)
movq %r15, 24(%rdi)
+ popq %rbp
popq %r15
popq %r14
popq %r13
popq %r12
- popq %rbp
popq %rbx
repz retq
#ifndef __APPLE__
.size sp_256_mont_mul_avx2_4,.-sp_256_mont_mul_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
*
* r Result of squaring.
@@ -39725,6 +40377,276 @@ _sp_256_mont_sqr_avx2_4:
#ifndef __APPLE__
.size sp_256_mont_sqr_avx2_4,.-sp_256_mont_sqr_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_cond_sub_avx2_4
+.type sp_256_cond_sub_avx2_4,@function
+.align 16
+sp_256_cond_sub_avx2_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_cond_sub_avx2_4
+.p2align 4
+_sp_256_cond_sub_avx2_4:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq $0x00, %rax
+ movq (%rdx), %r12
+ movq 8(%rdx), %r13
+ movq 16(%rdx), %r14
+ movq 24(%rdx), %r15
+ andq %rcx, %r12
+ andq %rcx, %r13
+ andq %rcx, %r14
+ andq %rcx, %r15
+ movq (%rsi), %r8
+ movq 8(%rsi), %r9
+ movq 16(%rsi), %r10
+ movq 24(%rsi), %r11
+ subq %r12, %r8
+ sbbq %r13, %r9
+ sbbq %r14, %r10
+ sbbq %r15, %r11
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq %r11, 24(%rdi)
+ sbbq $0x00, %rax
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_256_cond_sub_avx2_4,.-sp_256_cond_sub_avx2_4
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Reduce the number back to 256 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_mont_reduce_avx2_4
+.type sp_256_mont_reduce_avx2_4,@function
+.align 16
+sp_256_mont_reduce_avx2_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_mont_reduce_avx2_4
+.p2align 4
+_sp_256_mont_reduce_avx2_4:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq %rbx
+ movq %rdx, %rax
+ movq (%rdi), %r12
+ movq 8(%rdi), %r13
+ movq 16(%rdi), %r14
+ movq 24(%rdi), %r15
+ xorq %r11, %r11
+ xorq %r10, %r10
+ # a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp)
+ movq 32(%rdi), %rbx
+ # mu = a[0] * mp
+ movq %r12, %rdx
+ mulxq %rax, %rdx, %rcx
+ # a[0] += m[0] * mu
+ mulx (%rsi), %r8, %r9
+ adcxq %r8, %r12
+ # a[1] += m[1] * mu
+ mulx 8(%rsi), %r8, %rcx
+ adoxq %r9, %r13
+ adcxq %r8, %r13
+ # a[2] += m[2] * mu
+ mulx 16(%rsi), %r8, %r9
+ adoxq %rcx, %r14
+ adcxq %r8, %r14
+ # a[3] += m[3] * mu
+ mulx 24(%rsi), %r8, %rcx
+ adoxq %r9, %r15
+ adcxq %r8, %r15
+ # a[4] += carry
+ adoxq %rcx, %rbx
+ adcxq %r10, %rbx
+ # carry
+ adoxq %r10, %r11
+ adcxq %r10, %r11
+ # a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp)
+ movq 40(%rdi), %r12
+ # mu = a[1] * mp
+ movq %r13, %rdx
+ mulxq %rax, %rdx, %rcx
+ # a[1] += m[0] * mu
+ mulx (%rsi), %r8, %r9
+ adcxq %r8, %r13
+ # a[2] += m[1] * mu
+ mulx 8(%rsi), %r8, %rcx
+ adoxq %r9, %r14
+ adcxq %r8, %r14
+ # a[3] += m[2] * mu
+ mulx 16(%rsi), %r8, %r9
+ adoxq %rcx, %r15
+ adcxq %r8, %r15
+ # a[4] += m[3] * mu
+ mulx 24(%rsi), %r8, %rcx
+ adoxq %r9, %rbx
+ adcxq %r8, %rbx
+ # a[5] += carry
+ adoxq %rcx, %r12
+ adcxq %r11, %r12
+ movq %r10, %r11
+ # carry
+ adoxq %r10, %r11
+ adcxq %r10, %r11
+ # a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp)
+ movq 48(%rdi), %r13
+ # mu = a[2] * mp
+ movq %r14, %rdx
+ mulxq %rax, %rdx, %rcx
+ # a[2] += m[0] * mu
+ mulx (%rsi), %r8, %r9
+ adcxq %r8, %r14
+ # a[3] += m[1] * mu
+ mulx 8(%rsi), %r8, %rcx
+ adoxq %r9, %r15
+ adcxq %r8, %r15
+ # a[4] += m[2] * mu
+ mulx 16(%rsi), %r8, %r9
+ adoxq %rcx, %rbx
+ adcxq %r8, %rbx
+ # a[5] += m[3] * mu
+ mulx 24(%rsi), %r8, %rcx
+ adoxq %r9, %r12
+ adcxq %r8, %r12
+ # a[6] += carry
+ adoxq %rcx, %r13
+ adcxq %r11, %r13
+ movq %r10, %r11
+ # carry
+ adoxq %r10, %r11
+ adcxq %r10, %r11
+ # a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp)
+ movq 56(%rdi), %r14
+ # mu = a[3] * mp
+ movq %r15, %rdx
+ mulxq %rax, %rdx, %rcx
+ # a[3] += m[0] * mu
+ mulx (%rsi), %r8, %r9
+ adcxq %r8, %r15
+ # a[4] += m[1] * mu
+ mulx 8(%rsi), %r8, %rcx
+ adoxq %r9, %rbx
+ adcxq %r8, %rbx
+ # a[5] += m[2] * mu
+ mulx 16(%rsi), %r8, %r9
+ adoxq %rcx, %r12
+ adcxq %r8, %r12
+ # a[6] += m[3] * mu
+ mulx 24(%rsi), %r8, %rcx
+ adoxq %r9, %r13
+ adcxq %r8, %r13
+ # a[7] += carry
+ adoxq %rcx, %r14
+ adcxq %r11, %r14
+ movq %r10, %r11
+ # carry
+ adoxq %r10, %r11
+ adcxq %r10, %r11
+ # Subtract mod if carry
+ negq %r11
+ movq $0xf3b9cac2fc632551, %r8
+ movq $0xbce6faada7179e84, %r9
+ movq $0xffffffff00000000, %rdx
+ andq %r11, %r8
+ andq %r11, %r9
+ andq %r11, %rdx
+ subq %r8, %rbx
+ sbbq %r9, %r12
+ sbbq %r11, %r13
+ sbbq %rdx, %r14
+ movq %rbx, (%rdi)
+ movq %r12, 8(%rdi)
+ movq %r13, 16(%rdi)
+ movq %r14, 24(%rdi)
+ popq %rbx
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_256_mont_reduce_avx2_4,.-sp_256_mont_reduce_avx2_4
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_256_div2_avx2_4
+.type sp_256_div2_avx2_4,@function
+.align 16
+sp_256_div2_avx2_4:
+#else
+.section __TEXT,__text
+.globl _sp_256_div2_avx2_4
+.p2align 4
+_sp_256_div2_avx2_4:
+#endif /* __APPLE__ */
+ movq (%rsi), %rdx
+ movq 8(%rsi), %rax
+ movq 16(%rsi), %rcx
+ movq 24(%rsi), %r8
+ movq $0xffffffff, %r9
+ movq $0xffffffff00000001, %r10
+ movq %rdx, %r11
+ andq $0x01, %r11
+ negq %r11
+ andq %r11, %r9
+ andq %r11, %r10
+ addq %r11, %rdx
+ adcq %r9, %rax
+ adcq $0x00, %rcx
+ adcq %r10, %r8
+ movq $0x00, %r11
+ adcq $0x00, %r11
+ shrdq $0x01, %rax, %rdx
+ shrdq $0x01, %rcx, %rax
+ shrdq $0x01, %r8, %rcx
+ shrdq $0x01, %r11, %r8
+ movq %rdx, (%rdi)
+ movq %rax, 8(%rdi)
+ movq %rcx, 16(%rdi)
+ movq %r8, 24(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_256_div2_avx2_4,.-sp_256_div2_avx2_4
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifndef WC_NO_CACHE_RESISTANT
/* Touch each possible entry that could be being copied.
*
@@ -39784,6 +40706,7 @@ L_256_get_entry_64_4_start:
#ifndef __APPLE__
.size sp_256_get_entry_64_4,.-sp_256_get_entry_64_4
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Touch each possible entry that could be being copied.
*
* r Point to copy into.
@@ -39816,8 +40739,8 @@ _sp_256_get_entry_64_avx2_4:
L_256_get_entry_64_avx2_4_start:
vpcmpeqd %ymm5, %ymm6, %ymm4
vpaddd %ymm7, %ymm6, %ymm6
- vmovdqu (%rsi), %ymm2
- vmovdqu 32(%rsi), %ymm3
+ vmovupd (%rsi), %ymm2
+ vmovupd 32(%rsi), %ymm3
addq $0x40, %rsi
vpand %ymm4, %ymm2, %ymm2
vpand %ymm4, %ymm3, %ymm3
@@ -39825,12 +40748,13 @@ L_256_get_entry_64_avx2_4_start:
vpor %ymm3, %ymm1, %ymm1
decq %rax
jnz L_256_get_entry_64_avx2_4_start
- vmovdqu %ymm0, (%rdi)
- vmovdqu %ymm1, 64(%rdi)
+ vmovupd %ymm0, (%rdi)
+ vmovupd %ymm1, 64(%rdi)
repz retq
#ifndef __APPLE__
.size sp_256_get_entry_64_avx2_4,.-sp_256_get_entry_64_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WC_NO_CACHE_RESISTANT */
#ifndef WC_NO_CACHE_RESISTANT
/* Touch each possible entry that could be being copied.
@@ -39891,6 +40815,7 @@ L_256_get_entry_65_4_start:
#ifndef __APPLE__
.size sp_256_get_entry_65_4,.-sp_256_get_entry_65_4
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Touch each possible entry that could be being copied.
*
* r Point to copy into.
@@ -39923,8 +40848,8 @@ _sp_256_get_entry_65_avx2_4:
L_256_get_entry_65_avx2_4_start:
vpcmpeqd %ymm5, %ymm6, %ymm4
vpaddd %ymm7, %ymm6, %ymm6
- vmovdqu (%rsi), %ymm2
- vmovdqu 32(%rsi), %ymm3
+ vmovupd (%rsi), %ymm2
+ vmovupd 32(%rsi), %ymm3
addq $0x40, %rsi
vpand %ymm4, %ymm2, %ymm2
vpand %ymm4, %ymm3, %ymm3
@@ -39932,12 +40857,13 @@ L_256_get_entry_65_avx2_4_start:
vpor %ymm3, %ymm1, %ymm1
decq %rax
jnz L_256_get_entry_65_avx2_4_start
- vmovdqu %ymm0, (%rdi)
- vmovdqu %ymm1, 64(%rdi)
+ vmovupd %ymm0, (%rdi)
+ vmovupd %ymm1, 64(%rdi)
repz retq
#ifndef __APPLE__
.size sp_256_get_entry_65_avx2_4,.-sp_256_get_entry_65_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WC_NO_CACHE_RESISTANT */
/* Add 1 to a. (a = a + 1)
*
@@ -40057,6 +40983,7 @@ L_256_from_bin_bswap_zero_end:
#ifndef __APPLE__
.size sp_256_from_bin_bswap,.-sp_256_from_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Read big endian unsigned byte array into r.
* Uses the movbe instruction which is an optional instruction.
*
@@ -40142,6 +41069,7 @@ L_256_from_bin_movbe_zero_end:
#ifndef __APPLE__
.size sp_256_from_bin_movbe,.-sp_256_from_bin_movbe
#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 32
* Uses the bswap instruction.
@@ -40177,6 +41105,7 @@ _sp_256_to_bin_bswap:
#ifndef __APPLE__
.size sp_256_to_bin_bswap,.-sp_256_to_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 32
* Uses the movbe instruction which is optional.
@@ -40208,183 +41137,8 @@ _sp_256_to_bin_movbe:
#ifndef __APPLE__
.size sp_256_to_bin_movbe,.-sp_256_to_bin_movbe
#endif /* __APPLE__ */
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_256_add_4
-.type sp_256_add_4,@function
-.align 16
-sp_256_add_4:
-#else
-.section __TEXT,__text
-.globl _sp_256_add_4
-.p2align 4
-_sp_256_add_4:
-#endif /* __APPLE__ */
- # Add
- movq (%rsi), %rcx
- xorq %rax, %rax
- addq (%rdx), %rcx
- movq 8(%rsi), %r8
- movq %rcx, (%rdi)
- adcq 8(%rdx), %r8
- movq 16(%rsi), %rcx
- movq %r8, 8(%rdi)
- adcq 16(%rdx), %rcx
- movq 24(%rsi), %r8
- movq %rcx, 16(%rdi)
- adcq 24(%rdx), %r8
- movq %r8, 24(%rdi)
- adcq $0x00, %rax
- repz retq
-#ifndef __APPLE__
-.size sp_256_add_4,.-sp_256_add_4
-#endif /* __APPLE__ */
-/* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_256_mul_4
-.type sp_256_mul_4,@function
-.align 16
-sp_256_mul_4:
-#else
-.section __TEXT,__text
-.globl _sp_256_mul_4
-.p2align 4
-_sp_256_mul_4:
-#endif /* __APPLE__ */
- movq %rdx, %rcx
- subq $32, %rsp
- # A[0] * B[0]
- movq (%rcx), %rax
- mulq (%rsi)
- xorq %r10, %r10
- movq %rax, (%rsp)
- movq %rdx, %r9
- # A[0] * B[1]
- movq 8(%rcx), %rax
- mulq (%rsi)
- xorq %r8, %r8
- addq %rax, %r9
- adcq %rdx, %r10
- adcq $0x00, %r8
- # A[1] * B[0]
- movq (%rcx), %rax
- mulq 8(%rsi)
- addq %rax, %r9
- adcq %rdx, %r10
- adcq $0x00, %r8
- movq %r9, 8(%rsp)
- # A[0] * B[2]
- movq 16(%rcx), %rax
- mulq (%rsi)
- xorq %r9, %r9
- addq %rax, %r10
- adcq %rdx, %r8
- adcq $0x00, %r9
- # A[1] * B[1]
- movq 8(%rcx), %rax
- mulq 8(%rsi)
- addq %rax, %r10
- adcq %rdx, %r8
- adcq $0x00, %r9
- # A[2] * B[0]
- movq (%rcx), %rax
- mulq 16(%rsi)
- addq %rax, %r10
- adcq %rdx, %r8
- adcq $0x00, %r9
- movq %r10, 16(%rsp)
- # A[0] * B[3]
- movq 24(%rcx), %rax
- mulq (%rsi)
- xorq %r10, %r10
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %r10
- # A[1] * B[2]
- movq 16(%rcx), %rax
- mulq 8(%rsi)
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %r10
- # A[2] * B[1]
- movq 8(%rcx), %rax
- mulq 16(%rsi)
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %r10
- # A[3] * B[0]
- movq (%rcx), %rax
- mulq 24(%rsi)
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %r10
- movq %r8, 24(%rsp)
- # A[1] * B[3]
- movq 24(%rcx), %rax
- mulq 8(%rsi)
- xorq %r8, %r8
- addq %rax, %r9
- adcq %rdx, %r10
- adcq $0x00, %r8
- # A[2] * B[2]
- movq 16(%rcx), %rax
- mulq 16(%rsi)
- addq %rax, %r9
- adcq %rdx, %r10
- adcq $0x00, %r8
- # A[3] * B[1]
- movq 8(%rcx), %rax
- mulq 24(%rsi)
- addq %rax, %r9
- adcq %rdx, %r10
- adcq $0x00, %r8
- movq %r9, 32(%rdi)
- # A[2] * B[3]
- movq 24(%rcx), %rax
- mulq 16(%rsi)
- xorq %r9, %r9
- addq %rax, %r10
- adcq %rdx, %r8
- adcq $0x00, %r9
- # A[3] * B[2]
- movq 16(%rcx), %rax
- mulq 24(%rsi)
- addq %rax, %r10
- adcq %rdx, %r8
- adcq $0x00, %r9
- movq %r10, 40(%rdi)
- # A[3] * B[3]
- movq 24(%rcx), %rax
- mulq 24(%rsi)
- addq %rax, %r8
- adcq %rdx, %r9
- movq %r8, 48(%rdi)
- movq %r9, 56(%rdi)
- movq (%rsp), %rax
- movq 8(%rsp), %rdx
- movq 16(%rsp), %r8
- movq 24(%rsp), %r9
- movq %rax, (%rdi)
- movq %rdx, 8(%rdi)
- movq %r8, 16(%rdi)
- movq %r9, 24(%rdi)
- addq $32, %rsp
- repz retq
-#ifndef __APPLE__
-.size sp_256_mul_4,.-sp_256_mul_4
-#endif /* __APPLE__ */
+#endif /* NO_MOVBE_SUPPORT */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r Result of multiplication.
@@ -40404,11 +41158,11 @@ sp_256_mul_avx2_4:
_sp_256_mul_avx2_4:
#endif /* __APPLE__ */
pushq %rbx
- pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
+ pushq %rbp
movq %rdx, %rbp
# A[0] * B[0]
movq (%rbp), %rdx
@@ -40494,16 +41248,17 @@ _sp_256_mul_avx2_4:
movq %r13, 40(%rdi)
movq %r14, 48(%rdi)
movq %r15, 56(%rdi)
+ popq %rbp
popq %r15
popq %r14
popq %r13
popq %r12
- popq %rbp
popq %rbx
repz retq
#ifndef __APPLE__
.size sp_256_mul_avx2_4,.-sp_256_mul_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Sub b from a into a. (a -= b)
*
* a A single precision integer and result.
@@ -40535,60 +41290,6 @@ _sp_256_sub_in_place_4:
#ifndef __APPLE__
.size sp_256_sub_in_place_4,.-sp_256_sub_in_place_4
#endif /* __APPLE__ */
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
-#ifndef __APPLE__
-.text
-.globl sp_256_cond_sub_avx2_4
-.type sp_256_cond_sub_avx2_4,@function
-.align 16
-sp_256_cond_sub_avx2_4:
-#else
-.section __TEXT,__text
-.globl _sp_256_cond_sub_avx2_4
-.p2align 4
-_sp_256_cond_sub_avx2_4:
-#endif /* __APPLE__ */
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
- movq $0x00, %rax
- movq (%rdx), %r12
- movq 8(%rdx), %r13
- movq 16(%rdx), %r14
- movq 24(%rdx), %r15
- andq %rcx, %r12
- andq %rcx, %r13
- andq %rcx, %r14
- andq %rcx, %r15
- movq (%rsi), %r8
- movq 8(%rsi), %r9
- movq 16(%rsi), %r10
- movq 24(%rsi), %r11
- subq %r12, %r8
- sbbq %r13, %r9
- sbbq %r14, %r10
- sbbq %r15, %r11
- movq %r8, (%rdi)
- movq %r9, 8(%rdi)
- movq %r10, 16(%rdi)
- movq %r11, 24(%rdi)
- sbbq $0x00, %rax
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- repz retq
-#ifndef __APPLE__
-.size sp_256_cond_sub_avx2_4,.-sp_256_cond_sub_avx2_4
-#endif /* __APPLE__ */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -40671,14 +41372,14 @@ _sp_256_mul_d_avx2_4:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
@@ -40692,128 +41393,36 @@ _sp_256_mul_d_avx2_4:
.size sp_256_mul_d_avx2_4,.-sp_256_mul_d_avx2_4
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
-/* Square a and put result in r. (r = a * a)
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
*
- * r A single precision integer.
- * a A single precision integer.
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
*/
#ifndef __APPLE__
.text
-.globl sp_256_sqr_4
-.type sp_256_sqr_4,@function
+.globl div_256_word_asm_4
+.type div_256_word_asm_4,@function
.align 16
-sp_256_sqr_4:
+div_256_word_asm_4:
#else
.section __TEXT,__text
-.globl _sp_256_sqr_4
+.globl _div_256_word_asm_4
.p2align 4
-_sp_256_sqr_4:
+_div_256_word_asm_4:
#endif /* __APPLE__ */
- pushq %r12
- subq $32, %rsp
- # A[0] * A[0]
- movq (%rsi), %rax
- mulq %rax
- xorq %r9, %r9
- movq %rax, (%rsp)
- movq %rdx, %r8
- # A[0] * A[1]
- movq 8(%rsi), %rax
- mulq (%rsi)
- xorq %rcx, %rcx
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %rcx
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %rcx
- movq %r8, 8(%rsp)
- # A[0] * A[2]
- movq 16(%rsi), %rax
- mulq (%rsi)
- xorq %r8, %r8
- addq %rax, %r9
- adcq %rdx, %rcx
- adcq $0x00, %r8
- addq %rax, %r9
- adcq %rdx, %rcx
- adcq $0x00, %r8
- # A[1] * A[1]
- movq 8(%rsi), %rax
- mulq %rax
- addq %rax, %r9
- adcq %rdx, %rcx
- adcq $0x00, %r8
- movq %r9, 16(%rsp)
- # A[0] * A[3]
- movq 24(%rsi), %rax
- mulq (%rsi)
- xorq %r9, %r9
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq $0x00, %r9
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq $0x00, %r9
- # A[1] * A[2]
- movq 16(%rsi), %rax
- mulq 8(%rsi)
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq $0x00, %r9
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq $0x00, %r9
- movq %rcx, 24(%rsp)
- # A[1] * A[3]
- movq 24(%rsi), %rax
- mulq 8(%rsi)
- xorq %rcx, %rcx
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %rcx
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %rcx
- # A[2] * A[2]
- movq 16(%rsi), %rax
- mulq %rax
- addq %rax, %r8
- adcq %rdx, %r9
- adcq $0x00, %rcx
- movq %r8, 32(%rdi)
- # A[2] * A[3]
- movq 24(%rsi), %rax
- mulq 16(%rsi)
- xorq %r8, %r8
- addq %rax, %r9
- adcq %rdx, %rcx
- adcq $0x00, %r8
- addq %rax, %r9
- adcq %rdx, %rcx
- adcq $0x00, %r8
- movq %r9, 40(%rdi)
- # A[3] * A[3]
- movq 24(%rsi), %rax
- mulq %rax
- addq %rax, %rcx
- adcq %rdx, %r8
- movq %rcx, 48(%rdi)
- movq %r8, 56(%rdi)
- movq (%rsp), %rax
- movq 8(%rsp), %rdx
- movq 16(%rsp), %r10
- movq 24(%rsp), %r11
- movq %rax, (%rdi)
- movq %rdx, 8(%rdi)
- movq %r10, 16(%rdi)
- movq %r11, 24(%rdi)
- addq $32, %rsp
- popq %r12
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
repz retq
#ifndef __APPLE__
-.size sp_256_sqr_4,.-sp_256_sqr_4
+.size div_256_word_asm_4,.-div_256_word_asm_4
#endif /* __APPLE__ */
+#endif /* _WIN64 */
+#ifdef HAVE_INTEL_AVX2
/* Multiply two Montogmery form numbers mod the modulus (prime).
* (r = a * b mod m)
*
@@ -40834,11 +41443,11 @@ sp_256_mont_mul_order_avx2_4:
_sp_256_mont_mul_order_avx2_4:
#endif /* __APPLE__ */
pushq %rbx
- pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
+ pushq %rbp
movq %rdx, %rbp
# A[0] * B[0]
movq (%rbp), %rdx
@@ -40918,6 +41527,7 @@ _sp_256_mont_mul_order_avx2_4:
adoxq %rcx, %r15
# Start Reduction
movq $0xccd1c8aaee00bc4f, %rbx
+ # A[0]
movq %rbx, %rdx
imulq %r8, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -40942,6 +41552,7 @@ _sp_256_mont_mul_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[1]
movq %rbx, %rdx
imulq %r9, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -40966,6 +41577,7 @@ _sp_256_mont_mul_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[2]
movq %rbx, %rdx
imulq %r10, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -40990,6 +41602,7 @@ _sp_256_mont_mul_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[3]
movq %rbx, %rdx
imulq %r11, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -41029,16 +41642,18 @@ _sp_256_mont_mul_order_avx2_4:
sbbq %rbp, %r15
movq %r14, 16(%rdi)
movq %r15, 24(%rdi)
+ popq %rbp
popq %r15
popq %r14
popq %r13
popq %r12
- popq %rbp
popq %rbx
repz retq
#ifndef __APPLE__
.size sp_256_mont_mul_order_avx2_4,.-sp_256_mont_mul_order_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
*
* r Result of squaring.
@@ -41118,6 +41733,7 @@ _sp_256_mont_sqr_order_avx2_4:
adoxq %rbx, %r15
# Start Reduction
movq $0xccd1c8aaee00bc4f, %rbx
+ # A[0]
movq %rbx, %rdx
imulq %r8, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -41142,6 +41758,7 @@ _sp_256_mont_sqr_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[1]
movq %rbx, %rdx
imulq %r9, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -41166,6 +41783,7 @@ _sp_256_mont_sqr_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[2]
movq %rbx, %rdx
imulq %r10, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -41190,6 +41808,7 @@ _sp_256_mont_sqr_order_avx2_4:
# carry
adoxq %rbp, %r8
adcxq %rbp, %r8
+ # A[3]
movq %rbx, %rdx
imulq %r11, %rdx
movq $0xf3b9cac2fc632551, %rax
@@ -41239,6 +41858,7 @@ _sp_256_mont_sqr_order_avx2_4:
#ifndef __APPLE__
.size sp_256_mont_sqr_order_avx2_4,.-sp_256_mont_sqr_order_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
/* Non-constant time modular inversion.
*
* @param [out] r Resulting number.
@@ -41466,6 +42086,7 @@ L_256_mod_inv_4_store_end:
#ifndef __APPLE__
.size sp_256_mod_inv_4,.-sp_256_mod_inv_4
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
#ifndef __APPLE__
.data
#else
@@ -41569,15 +42190,15 @@ _sp_256_mod_inv_avx2_4:
movq 8(%rsi), %r11
movq 16(%rsi), %r12
movq 24(%rsi), %r13
- vmovdqu 0+L_sp256_mod_inv_avx2_4_order(%rip), %ymm6
- vmovdqu 32+L_sp256_mod_inv_avx2_4_order(%rip), %ymm7
- vmovdqu 0+L_sp256_mod_inv_avx2_4_one(%rip), %ymm8
- vmovdqu 0+L_sp256_mod_inv_avx2_4_mask01111(%rip), %ymm9
- vmovdqu 0+L_sp256_mod_inv_avx2_4_all_one(%rip), %ymm10
- vmovdqu L_sp256_mod_inv_avx2_4_down_one_dword(%rip), %ymm11
- vmovdqu L_sp256_mod_inv_avx2_4_neg(%rip), %ymm12
- vmovdqu L_sp256_mod_inv_avx2_4_up_one_dword(%rip), %ymm13
- vmovdqu L_sp256_mod_inv_avx2_4_mask26(%rip), %ymm14
+ vmovupd 0+L_sp256_mod_inv_avx2_4_order(%rip), %ymm6
+ vmovupd 32+L_sp256_mod_inv_avx2_4_order(%rip), %ymm7
+ vmovupd 0+L_sp256_mod_inv_avx2_4_one(%rip), %ymm8
+ vmovupd 0+L_sp256_mod_inv_avx2_4_mask01111(%rip), %ymm9
+ vmovupd 0+L_sp256_mod_inv_avx2_4_all_one(%rip), %ymm10
+ vmovupd 0+L_sp256_mod_inv_avx2_4_down_one_dword(%rip), %ymm11
+ vmovupd 0+L_sp256_mod_inv_avx2_4_neg(%rip), %ymm12
+ vmovupd 0+L_sp256_mod_inv_avx2_4_up_one_dword(%rip), %ymm13
+ vmovupd 0+L_sp256_mod_inv_avx2_4_mask26(%rip), %ymm14
vpxor %xmm0, %xmm0, %xmm0
vpxor %xmm1, %xmm1, %xmm1
vmovdqu %ymm8, %ymm2
@@ -41794,55 +42415,9 @@ L_256_mod_inv_avx2_4_store_done:
#ifndef __APPLE__
.size sp_256_mod_inv_avx2_4,.-sp_256_mod_inv_avx2_4
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WOLFSSL_SP_NO_256 */
#ifdef WOLFSSL_SP_384
-/* Conditionally copy a into r using the mask m.
- * m is -1 to copy and 0 when not.
- *
- * r A single precision number to copy over.
- * a A single precision number to copy.
- * m Mask value to apply.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_cond_copy_6
-.type sp_384_cond_copy_6,@function
-.align 16
-sp_384_cond_copy_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_cond_copy_6
-.p2align 4
-_sp_384_cond_copy_6:
-#endif /* __APPLE__ */
- movq (%rdi), %rax
- movq 8(%rdi), %rcx
- movq 16(%rdi), %r8
- movq 24(%rdi), %r9
- movq 32(%rdi), %r10
- movq 40(%rdi), %r11
- xorq (%rsi), %rax
- xorq 8(%rsi), %rcx
- xorq 16(%rsi), %r8
- xorq 24(%rsi), %r9
- xorq 32(%rsi), %r10
- xorq 40(%rsi), %r11
- andq %rdx, %rax
- andq %rdx, %rcx
- andq %rdx, %r8
- andq %rdx, %r9
- andq %rdx, %r10
- andq %rdx, %r11
- xorq %rax, (%rdi)
- xorq %rcx, 8(%rdi)
- xorq %r8, 16(%rdi)
- xorq %r9, 24(%rdi)
- xorq %r10, 32(%rdi)
- xorq %r11, 40(%rdi)
- repz retq
-#ifndef __APPLE__
-.size sp_384_cond_copy_6,.-sp_384_cond_copy_6
-#endif /* __APPLE__ */
/* Multiply a and b into r. (r = a * b)
*
* r A single precision integer.
@@ -42115,371 +42690,6 @@ _sp_384_mul_6:
#ifndef __APPLE__
.size sp_384_mul_6,.-sp_384_mul_6
#endif /* __APPLE__ */
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_cond_sub_6
-.type sp_384_cond_sub_6,@function
-.align 16
-sp_384_cond_sub_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_cond_sub_6
-.p2align 4
-_sp_384_cond_sub_6:
-#endif /* __APPLE__ */
- subq $48, %rsp
- movq $0x00, %rax
- movq (%rdx), %r8
- movq 8(%rdx), %r9
- andq %rcx, %r8
- andq %rcx, %r9
- movq %r8, (%rsp)
- movq %r9, 8(%rsp)
- movq 16(%rdx), %r8
- movq 24(%rdx), %r9
- andq %rcx, %r8
- andq %rcx, %r9
- movq %r8, 16(%rsp)
- movq %r9, 24(%rsp)
- movq 32(%rdx), %r8
- movq 40(%rdx), %r9
- andq %rcx, %r8
- andq %rcx, %r9
- movq %r8, 32(%rsp)
- movq %r9, 40(%rsp)
- movq (%rsi), %r8
- movq (%rsp), %rdx
- subq %rdx, %r8
- movq 8(%rsi), %r9
- movq 8(%rsp), %rdx
- sbbq %rdx, %r9
- movq %r8, (%rdi)
- movq 16(%rsi), %r8
- movq 16(%rsp), %rdx
- sbbq %rdx, %r8
- movq %r9, 8(%rdi)
- movq 24(%rsi), %r9
- movq 24(%rsp), %rdx
- sbbq %rdx, %r9
- movq %r8, 16(%rdi)
- movq 32(%rsi), %r8
- movq 32(%rsp), %rdx
- sbbq %rdx, %r8
- movq %r9, 24(%rdi)
- movq 40(%rsi), %r9
- movq 40(%rsp), %rdx
- sbbq %rdx, %r9
- movq %r8, 32(%rdi)
- movq %r9, 40(%rdi)
- sbbq $0x00, %rax
- addq $48, %rsp
- repz retq
-#ifndef __APPLE__
-.size sp_384_cond_sub_6,.-sp_384_cond_sub_6
-#endif /* __APPLE__ */
-#ifdef HAVE_INTEL_AVX2
-/* Reduce the number back to 384 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_mont_reduce_6
-.type sp_384_mont_reduce_6,@function
-.align 16
-sp_384_mont_reduce_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_mont_reduce_6
-.p2align 4
-_sp_384_mont_reduce_6:
-#endif /* __APPLE__ */
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
- pushq %rbx
- pushq %rbp
- movq (%rdi), %r11
- movq 8(%rdi), %r12
- movq 16(%rdi), %r13
- movq 24(%rdi), %r14
- movq 32(%rdi), %r15
- movq 40(%rdi), %rsi
- xorq %r10, %r10
- # a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp)
- movq 48(%rdi), %rbx
- movq 56(%rdi), %rbp
- movq %r11, %rdx
- movq %r12, %rax
- shldq $32, %rdx, %rax
- shlq $32, %rdx
- addq %r11, %rdx
- adcq %r12, %rax
- addq %r11, %rax
- movq %rdx, %rcx
- movq %rax, %r8
- movq %rax, %r9
- shldq $32, %rcx, %r8
- shlq $32, %rcx
- shrq $32, %r9
- addq %rcx, %r11
- adcq %r8, %r12
- adcq %r9, %r13
- adcq $0x00, %r14
- adcq $0x00, %r15
- adcq $0x00, %rsi
- adcq %rdx, %rbx
- adcq %rax, %rbp
- adcq $0x00, %r10
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq %rax, %r9
- movq $0x00, %rax
- adcq $0x00, %rax
- subq %r8, %r13
- sbbq %r9, %r14
- sbbq %rax, %r15
- sbbq $0x00, %rsi
- sbbq $0x00, %rbx
- sbbq $0x00, %rbp
- sbbq $0x00, %r10
- # a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp)
- movq 64(%rdi), %r11
- movq 72(%rdi), %r12
- movq %r13, %rdx
- movq %r14, %rax
- shldq $32, %rdx, %rax
- shlq $32, %rdx
- addq %r13, %rdx
- adcq %r14, %rax
- addq %r13, %rax
- movq %rdx, %rcx
- movq %rax, %r8
- movq %rax, %r9
- shldq $32, %rcx, %r8
- shlq $32, %rcx
- shrq $32, %r9
- addq %r10, %r11
- adcq $0x00, %r12
- movq $0x00, %r10
- adcq $0x00, %r10
- addq %rcx, %r13
- adcq %r8, %r14
- adcq %r9, %r15
- adcq $0x00, %rsi
- adcq $0x00, %rbx
- adcq $0x00, %rbp
- adcq %rdx, %r11
- adcq %rax, %r12
- adcq $0x00, %r10
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq %rax, %r9
- movq $0x00, %rax
- adcq $0x00, %rax
- subq %r8, %r15
- sbbq %r9, %rsi
- sbbq %rax, %rbx
- sbbq $0x00, %rbp
- sbbq $0x00, %r11
- sbbq $0x00, %r12
- sbbq $0x00, %r10
- # a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp)
- movq 80(%rdi), %r13
- movq 88(%rdi), %r14
- movq %r15, %rdx
- movq %rsi, %rax
- shldq $32, %rdx, %rax
- shlq $32, %rdx
- addq %r15, %rdx
- adcq %rsi, %rax
- addq %r15, %rax
- movq %rdx, %rcx
- movq %rax, %r8
- movq %rax, %r9
- shldq $32, %rcx, %r8
- shlq $32, %rcx
- shrq $32, %r9
- addq %r10, %r13
- adcq $0x00, %r14
- movq $0x00, %r10
- adcq $0x00, %r10
- addq %rcx, %r15
- adcq %r8, %rsi
- adcq %r9, %rbx
- adcq $0x00, %rbp
- adcq $0x00, %r11
- adcq $0x00, %r12
- adcq %rdx, %r13
- adcq %rax, %r14
- adcq $0x00, %r10
- addq %rax, %rcx
- adcq %rdx, %r8
- adcq %rax, %r9
- movq $0x00, %rax
- adcq $0x00, %rax
- subq %r8, %rbx
- sbbq %r9, %rbp
- sbbq %rax, %r11
- sbbq $0x00, %r12
- sbbq $0x00, %r13
- sbbq $0x00, %r14
- sbbq $0x00, %r10
- # Subtract mod if carry
- negq %r10
- movq $0xfffffffffffffffe, %r9
- movq %r10, %rcx
- movq %r10, %r8
- shrq $32, %rcx
- shlq $32, %r8
- andq %r10, %r9
- subq %rcx, %rbx
- sbbq %r8, %rbp
- sbbq %r9, %r11
- sbbq %r10, %r12
- sbbq %r10, %r13
- sbbq %r10, %r14
- movq %rbx, (%rdi)
- movq %rbp, 8(%rdi)
- movq %r11, 16(%rdi)
- movq %r12, 24(%rdi)
- movq %r13, 32(%rdi)
- movq %r14, 40(%rdi)
- popq %rbp
- popq %rbx
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- repz retq
-#ifndef __APPLE__
-.size sp_384_mont_reduce_6,.-sp_384_mont_reduce_6
-#endif /* __APPLE__ */
-#endif /* HAVE_INTEL_AVX2 */
-/* Reduce the number back to 384 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_mont_reduce_order_6
-.type sp_384_mont_reduce_order_6,@function
-.align 16
-sp_384_mont_reduce_order_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_mont_reduce_order_6
-.p2align 4
-_sp_384_mont_reduce_order_6:
-#endif /* __APPLE__ */
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
- movq %rdx, %rcx
- xorq %r15, %r15
- # i = 6
- movq $6, %r8
- movq (%rdi), %r13
- movq 8(%rdi), %r14
-L_mont_loop_order_6:
- # mu = a[i] * mp
- movq %r13, %r11
- imulq %rcx, %r11
- # a[i+0] += m[0] * mu
- movq %r11, %rax
- xorq %r10, %r10
- mulq (%rsi)
- addq %rax, %r13
- adcq %rdx, %r10
- # a[i+1] += m[1] * mu
- movq %r11, %rax
- xorq %r9, %r9
- mulq 8(%rsi)
- movq %r14, %r13
- addq %rax, %r13
- adcq %rdx, %r9
- addq %r10, %r13
- adcq $0x00, %r9
- # a[i+2] += m[2] * mu
- movq %r11, %rax
- xorq %r10, %r10
- mulq 16(%rsi)
- movq 16(%rdi), %r14
- addq %rax, %r14
- adcq %rdx, %r10
- addq %r9, %r14
- adcq $0x00, %r10
- # a[i+3] += m[3] * mu
- movq %r11, %rax
- xorq %r9, %r9
- mulq 24(%rsi)
- movq 24(%rdi), %r12
- addq %rax, %r12
- adcq %rdx, %r9
- addq %r10, %r12
- movq %r12, 24(%rdi)
- adcq $0x00, %r9
- # a[i+4] += m[4] * mu
- movq %r11, %rax
- xorq %r10, %r10
- mulq 32(%rsi)
- movq 32(%rdi), %r12
- addq %rax, %r12
- adcq %rdx, %r10
- addq %r9, %r12
- movq %r12, 32(%rdi)
- adcq $0x00, %r10
- # a[i+5] += m[5] * mu
- movq %r11, %rax
- mulq 40(%rsi)
- movq 40(%rdi), %r12
- addq %rax, %r10
- adcq %r15, %rdx
- movq $0x00, %r15
- adcq $0x00, %r15
- addq %r10, %r12
- movq %r12, 40(%rdi)
- adcq %rdx, 48(%rdi)
- adcq $0x00, %r15
- # i -= 1
- addq $8, %rdi
- decq %r8
- jnz L_mont_loop_order_6
- movq %r13, (%rdi)
- movq %r14, 8(%rdi)
- negq %r15
- movq %r15, %rcx
- movq %rsi, %rdx
- movq %rdi, %rsi
- movq %rdi, %rdi
- subq $48, %rdi
-#ifndef __APPLE__
- callq sp_384_cond_sub_6@plt
-#else
- callq _sp_384_cond_sub_6
-#endif /* __APPLE__ */
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- repz retq
-#ifndef __APPLE__
-.size sp_384_mont_reduce_order_6,.-sp_384_mont_reduce_order_6
-#endif /* __APPLE__ */
/* Square a and put result in r. (r = a * a)
*
* r A single precision integer.
@@ -42704,6 +42914,508 @@ _sp_384_sqr_6:
#ifndef __APPLE__
.size sp_384_sqr_6,.-sp_384_sqr_6
#endif /* __APPLE__ */
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_add_6
+.type sp_384_add_6,@function
+.align 16
+sp_384_add_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_add_6
+.p2align 4
+_sp_384_add_6:
+#endif /* __APPLE__ */
+ # Add
+ movq (%rsi), %rcx
+ xorq %rax, %rax
+ addq (%rdx), %rcx
+ movq 8(%rsi), %r8
+ movq %rcx, (%rdi)
+ adcq 8(%rdx), %r8
+ movq 16(%rsi), %rcx
+ movq %r8, 8(%rdi)
+ adcq 16(%rdx), %rcx
+ movq 24(%rsi), %r8
+ movq %rcx, 16(%rdi)
+ adcq 24(%rdx), %r8
+ movq 32(%rsi), %rcx
+ movq %r8, 24(%rdi)
+ adcq 32(%rdx), %rcx
+ movq 40(%rsi), %r8
+ movq %rcx, 32(%rdi)
+ adcq 40(%rdx), %r8
+ movq %r8, 40(%rdi)
+ adcq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_384_add_6,.-sp_384_add_6
+#endif /* __APPLE__ */
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_sub_6
+.type sp_384_sub_6,@function
+.align 16
+sp_384_sub_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_sub_6
+.p2align 4
+_sp_384_sub_6:
+#endif /* __APPLE__ */
+ pushq %r12
+ xorq %rax, %rax
+ movq (%rsi), %rcx
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ movq 32(%rsi), %r11
+ movq 40(%rsi), %r12
+ subq (%rdx), %rcx
+ sbbq 8(%rdx), %r8
+ sbbq 16(%rdx), %r9
+ sbbq 24(%rdx), %r10
+ sbbq 32(%rdx), %r11
+ sbbq 40(%rdx), %r12
+ movq %rcx, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ movq %r11, 32(%rdi)
+ movq %r12, 40(%rdi)
+ sbbq $0x00, %rax
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_384_sub_6,.-sp_384_sub_6
+#endif /* __APPLE__ */
+/* Conditionally copy a into r using the mask m.
+ * m is -1 to copy and 0 when not.
+ *
+ * r A single precision number to copy over.
+ * a A single precision number to copy.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_cond_copy_6
+.type sp_384_cond_copy_6,@function
+.align 16
+sp_384_cond_copy_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_cond_copy_6
+.p2align 4
+_sp_384_cond_copy_6:
+#endif /* __APPLE__ */
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ movq 32(%rdi), %r10
+ movq 40(%rdi), %r11
+ xorq (%rsi), %rax
+ xorq 8(%rsi), %rcx
+ xorq 16(%rsi), %r8
+ xorq 24(%rsi), %r9
+ xorq 32(%rsi), %r10
+ xorq 40(%rsi), %r11
+ andq %rdx, %rax
+ andq %rdx, %rcx
+ andq %rdx, %r8
+ andq %rdx, %r9
+ andq %rdx, %r10
+ andq %rdx, %r11
+ xorq %rax, (%rdi)
+ xorq %rcx, 8(%rdi)
+ xorq %r8, 16(%rdi)
+ xorq %r9, 24(%rdi)
+ xorq %r10, 32(%rdi)
+ xorq %r11, 40(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_384_cond_copy_6,.-sp_384_cond_copy_6
+#endif /* __APPLE__ */
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_cond_sub_6
+.type sp_384_cond_sub_6,@function
+.align 16
+sp_384_cond_sub_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_cond_sub_6
+.p2align 4
+_sp_384_cond_sub_6:
+#endif /* __APPLE__ */
+ subq $48, %rsp
+ movq $0x00, %rax
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, (%rsp)
+ movq %r9, 8(%rsp)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 16(%rsp)
+ movq %r9, 24(%rsp)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 32(%rsp)
+ movq %r9, 40(%rsp)
+ movq (%rsi), %r8
+ movq (%rsp), %rdx
+ subq %rdx, %r8
+ movq 8(%rsi), %r9
+ movq 8(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, (%rdi)
+ movq 16(%rsi), %r8
+ movq 16(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 8(%rdi)
+ movq 24(%rsi), %r9
+ movq 24(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 16(%rdi)
+ movq 32(%rsi), %r8
+ movq 32(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 24(%rdi)
+ movq 40(%rsi), %r9
+ movq 40(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ sbbq $0x00, %rax
+ addq $48, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_384_cond_sub_6,.-sp_384_cond_sub_6
+#endif /* __APPLE__ */
+/* Reduce the number back to 384 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_mont_reduce_6
+.type sp_384_mont_reduce_6,@function
+.align 16
+sp_384_mont_reduce_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_mont_reduce_6
+.p2align 4
+_sp_384_mont_reduce_6:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
+ movq (%rdi), %r11
+ movq 8(%rdi), %r12
+ movq 16(%rdi), %r13
+ movq 24(%rdi), %r14
+ movq 32(%rdi), %r15
+ movq 40(%rdi), %rsi
+ xorq %r10, %r10
+ # a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp)
+ movq 48(%rdi), %rbx
+ movq 56(%rdi), %rbp
+ movq %r11, %rdx
+ movq %r12, %rax
+ shldq $32, %rdx, %rax
+ shlq $32, %rdx
+ addq %r11, %rdx
+ adcq %r12, %rax
+ addq %r11, %rax
+ movq %rdx, %rcx
+ movq %rax, %r8
+ movq %rax, %r9
+ shldq $32, %rcx, %r8
+ shlq $32, %rcx
+ shrq $32, %r9
+ addq %rcx, %r11
+ adcq %r8, %r12
+ adcq %r9, %r13
+ adcq $0x00, %r14
+ adcq $0x00, %r15
+ adcq $0x00, %rsi
+ adcq %rdx, %rbx
+ adcq %rax, %rbp
+ adcq $0x00, %r10
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq %rax, %r9
+ movq $0x00, %rax
+ adcq $0x00, %rax
+ subq %r8, %r13
+ sbbq %r9, %r14
+ sbbq %rax, %r15
+ sbbq $0x00, %rsi
+ sbbq $0x00, %rbx
+ sbbq $0x00, %rbp
+ sbbq $0x00, %r10
+ # a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp)
+ movq 64(%rdi), %r11
+ movq 72(%rdi), %r12
+ movq %r13, %rdx
+ movq %r14, %rax
+ shldq $32, %rdx, %rax
+ shlq $32, %rdx
+ addq %r13, %rdx
+ adcq %r14, %rax
+ addq %r13, %rax
+ movq %rdx, %rcx
+ movq %rax, %r8
+ movq %rax, %r9
+ shldq $32, %rcx, %r8
+ shlq $32, %rcx
+ shrq $32, %r9
+ addq %r10, %r11
+ adcq $0x00, %r12
+ movq $0x00, %r10
+ adcq $0x00, %r10
+ addq %rcx, %r13
+ adcq %r8, %r14
+ adcq %r9, %r15
+ adcq $0x00, %rsi
+ adcq $0x00, %rbx
+ adcq $0x00, %rbp
+ adcq %rdx, %r11
+ adcq %rax, %r12
+ adcq $0x00, %r10
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq %rax, %r9
+ movq $0x00, %rax
+ adcq $0x00, %rax
+ subq %r8, %r15
+ sbbq %r9, %rsi
+ sbbq %rax, %rbx
+ sbbq $0x00, %rbp
+ sbbq $0x00, %r11
+ sbbq $0x00, %r12
+ sbbq $0x00, %r10
+ # a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp)
+ movq 80(%rdi), %r13
+ movq 88(%rdi), %r14
+ movq %r15, %rdx
+ movq %rsi, %rax
+ shldq $32, %rdx, %rax
+ shlq $32, %rdx
+ addq %r15, %rdx
+ adcq %rsi, %rax
+ addq %r15, %rax
+ movq %rdx, %rcx
+ movq %rax, %r8
+ movq %rax, %r9
+ shldq $32, %rcx, %r8
+ shlq $32, %rcx
+ shrq $32, %r9
+ addq %r10, %r13
+ adcq $0x00, %r14
+ movq $0x00, %r10
+ adcq $0x00, %r10
+ addq %rcx, %r15
+ adcq %r8, %rsi
+ adcq %r9, %rbx
+ adcq $0x00, %rbp
+ adcq $0x00, %r11
+ adcq $0x00, %r12
+ adcq %rdx, %r13
+ adcq %rax, %r14
+ adcq $0x00, %r10
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq %rax, %r9
+ movq $0x00, %rax
+ adcq $0x00, %rax
+ subq %r8, %rbx
+ sbbq %r9, %rbp
+ sbbq %rax, %r11
+ sbbq $0x00, %r12
+ sbbq $0x00, %r13
+ sbbq $0x00, %r14
+ sbbq $0x00, %r10
+ # Subtract mod if carry
+ negq %r10
+ movq $0xfffffffffffffffe, %r9
+ movq %r10, %rcx
+ movq %r10, %r8
+ shrq $32, %rcx
+ shlq $32, %r8
+ andq %r10, %r9
+ subq %rcx, %rbx
+ sbbq %r8, %rbp
+ sbbq %r9, %r11
+ sbbq %r10, %r12
+ sbbq %r10, %r13
+ sbbq %r10, %r14
+ movq %rbx, (%rdi)
+ movq %rbp, 8(%rdi)
+ movq %r11, 16(%rdi)
+ movq %r12, 24(%rdi)
+ movq %r13, 32(%rdi)
+ movq %r14, 40(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_384_mont_reduce_6,.-sp_384_mont_reduce_6
+#endif /* __APPLE__ */
+/* Reduce the number back to 384 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_mont_reduce_order_6
+.type sp_384_mont_reduce_order_6,@function
+.align 16
+sp_384_mont_reduce_order_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_mont_reduce_order_6
+.p2align 4
+_sp_384_mont_reduce_order_6:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rdx, %rcx
+ xorq %r15, %r15
+ # i = 6
+ movq $6, %r8
+ movq (%rdi), %r13
+ movq 8(%rdi), %r14
+L_384_mont_loop_order_6:
+ # mu = a[i] * mp
+ movq %r13, %r11
+ imulq %rcx, %r11
+ # a[i+0] += m[0] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq (%rsi)
+ addq %rax, %r13
+ adcq %rdx, %r10
+ # a[i+1] += m[1] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 8(%rsi)
+ movq %r14, %r13
+ addq %rax, %r13
+ adcq %rdx, %r9
+ addq %r10, %r13
+ adcq $0x00, %r9
+ # a[i+2] += m[2] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 16(%rsi)
+ movq 16(%rdi), %r14
+ addq %rax, %r14
+ adcq %rdx, %r10
+ addq %r9, %r14
+ adcq $0x00, %r10
+ # a[i+3] += m[3] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 24(%rsi)
+ movq 24(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 24(%rdi)
+ adcq $0x00, %r9
+ # a[i+4] += m[4] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 32(%rsi)
+ movq 32(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 32(%rdi)
+ adcq $0x00, %r10
+ # a[i+5] += m[5] * mu
+ movq %r11, %rax
+ mulq 40(%rsi)
+ movq 40(%rdi), %r12
+ addq %rax, %r10
+ adcq %r15, %rdx
+ movq $0x00, %r15
+ adcq $0x00, %r15
+ addq %r10, %r12
+ movq %r12, 40(%rdi)
+ adcq %rdx, 48(%rdi)
+ adcq $0x00, %r15
+ # i -= 1
+ addq $8, %rdi
+ decq %r8
+ jnz L_384_mont_loop_order_6
+ movq %r13, (%rdi)
+ movq %r14, 8(%rdi)
+ negq %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
+ movq %r15, %rcx
+ movq %rsi, %rdx
+#endif /* _WIN64 */
+ movq %rdi, %rsi
+ movq %rdi, %rdi
+ subq $48, %rdi
+#ifndef __APPLE__
+ callq sp_384_cond_sub_6@plt
+#else
+ callq _sp_384_cond_sub_6
+#endif /* __APPLE__ */
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_384_mont_reduce_order_6,.-sp_384_mont_reduce_order_6
+#endif /* __APPLE__ */
/* Compare a with b in constant time.
*
* a A single precision integer.
@@ -42780,49 +43492,6 @@ _sp_384_cmp_6:
#ifndef __APPLE__
.size sp_384_cmp_6,.-sp_384_cmp_6
#endif /* __APPLE__ */
-/* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_add_6
-.type sp_384_add_6,@function
-.align 16
-sp_384_add_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_add_6
-.p2align 4
-_sp_384_add_6:
-#endif /* __APPLE__ */
- # Add
- movq (%rsi), %rcx
- xorq %rax, %rax
- addq (%rdx), %rcx
- movq 8(%rsi), %r8
- movq %rcx, (%rdi)
- adcq 8(%rdx), %r8
- movq 16(%rsi), %rcx
- movq %r8, 8(%rdi)
- adcq 16(%rdx), %rcx
- movq 24(%rsi), %r8
- movq %rcx, 16(%rdi)
- adcq 24(%rdx), %r8
- movq 32(%rsi), %rcx
- movq %r8, 24(%rdi)
- adcq 32(%rdx), %rcx
- movq 40(%rsi), %r8
- movq %rcx, 32(%rdi)
- adcq 40(%rdx), %r8
- movq %r8, 40(%rdi)
- adcq $0x00, %rax
- repz retq
-#ifndef __APPLE__
-.size sp_384_add_6,.-sp_384_add_6
-#endif /* __APPLE__ */
/* Add a to a into r. (r = a + a)
*
* r A single precision integer.
@@ -42864,50 +43533,6 @@ _sp_384_dbl_6:
#ifndef __APPLE__
.size sp_384_dbl_6,.-sp_384_dbl_6
#endif /* __APPLE__ */
-/* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_sub_6
-.type sp_384_sub_6,@function
-.align 16
-sp_384_sub_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_sub_6
-.p2align 4
-_sp_384_sub_6:
-#endif /* __APPLE__ */
- pushq %r12
- xorq %rax, %rax
- movq (%rsi), %rcx
- movq 8(%rsi), %r8
- movq 16(%rsi), %r9
- movq 24(%rsi), %r10
- movq 32(%rsi), %r11
- movq 40(%rsi), %r12
- subq (%rdx), %rcx
- sbbq 8(%rdx), %r8
- sbbq 16(%rdx), %r9
- sbbq 24(%rdx), %r10
- sbbq 32(%rdx), %r11
- sbbq 40(%rdx), %r12
- movq %rcx, (%rdi)
- movq %r8, 8(%rdi)
- movq %r9, 16(%rdi)
- movq %r10, 24(%rdi)
- movq %r11, 32(%rdi)
- movq %r12, 40(%rdi)
- sbbq $0x00, %rax
- popq %r12
- repz retq
-#ifndef __APPLE__
-.size sp_384_sub_6,.-sp_384_sub_6
-#endif /* __APPLE__ */
/* Conditionally add a and b using the mask m.
* m is -1 to add and 0 when not.
*
@@ -42997,11 +43622,11 @@ sp_384_div2_6:
_sp_384_div2_6:
#endif /* __APPLE__ */
subq $48, %rsp
- movq (%rsi), %rax
- movq %rax, %r11
+ movq (%rsi), %r11
+ xorq %r10, %r10
+ movq %r11, %rax
andq $0x01, %r11
negq %r11
- xorq %r10, %r10
movq (%rdx), %r8
andq %r11, %r8
movq %r8, (%rsp)
@@ -43155,6 +43780,7 @@ L_384_get_point_33_6_start_2:
#ifndef __APPLE__
.size sp_384_get_point_33_6,.-sp_384_get_point_33_6
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Touch each possible point that could be being copied.
*
* r Point to copy into.
@@ -43191,11 +43817,11 @@ _sp_384_get_point_33_avx2_6:
L_384_get_point_33_avx2_6_start:
vpcmpeqd %ymm13, %ymm14, %ymm12
vpaddd %ymm15, %ymm14, %ymm14
- vmovdqu (%rsi), %ymm6
+ vmovupd (%rsi), %ymm6
vmovdqu 32(%rsi), %xmm7
- vmovdqu 96(%rsi), %ymm8
+ vmovupd 96(%rsi), %ymm8
vmovdqu 128(%rsi), %xmm9
- vmovdqu 192(%rsi), %ymm10
+ vmovupd 192(%rsi), %ymm10
vmovdqu 224(%rsi), %xmm11
addq $0x128, %rsi
vpand %ymm12, %ymm6, %ymm6
@@ -43212,17 +43838,19 @@ L_384_get_point_33_avx2_6_start:
vpor %xmm11, %xmm5, %xmm5
decq %rax
jnz L_384_get_point_33_avx2_6_start
- vmovdqu %ymm0, (%rdi)
+ vmovupd %ymm0, (%rdi)
vmovdqu %xmm1, 32(%rdi)
- vmovdqu %ymm2, 96(%rdi)
+ vmovupd %ymm2, 96(%rdi)
vmovdqu %xmm3, 128(%rdi)
- vmovdqu %ymm4, 192(%rdi)
+ vmovupd %ymm4, 192(%rdi)
vmovdqu %xmm5, 224(%rdi)
repz retq
#ifndef __APPLE__
.size sp_384_get_point_33_avx2_6,.-sp_384_get_point_33_avx2_6
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WC_NO_CACHE_RESISTANT */
+#ifdef HAVE_INTEL_AVX2
/* Multiply a and b into r. (r = a * b)
*
* r Result of multiplication.
@@ -43445,6 +44073,7 @@ _sp_384_mul_avx2_6:
#ifndef __APPLE__
.size sp_384_mul_avx2_6,.-sp_384_mul_avx2_6
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifdef HAVE_INTEL_AVX2
/* Reduce the number back to 384 bits using Montgomery reduction.
*
@@ -43775,6 +44404,7 @@ L_mont_loop_order_avx2_6:
.size sp_384_mont_reduce_order_avx2_6,.-sp_384_mont_reduce_order_avx2_6
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
/* Square a and put result in r. (r = a * a)
*
* r Result of squaring.
@@ -43937,6 +44567,143 @@ _sp_384_sqr_avx2_6:
#ifndef __APPLE__
.size sp_384_sqr_avx2_6,.-sp_384_sqr_avx2_6
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_cond_sub_avx2_6
+.type sp_384_cond_sub_avx2_6,@function
+.align 16
+sp_384_cond_sub_avx2_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_cond_sub_avx2_6
+.p2align 4
+_sp_384_cond_sub_avx2_6:
+#endif /* __APPLE__ */
+ movq $0x00, %rax
+ movq (%rdx), %r10
+ movq (%rsi), %r8
+ pextq %rcx, %r10, %r10
+ subq %r10, %r8
+ movq 8(%rdx), %r10
+ movq 8(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, (%rdi)
+ sbbq %r10, %r9
+ movq 16(%rdx), %r8
+ movq 16(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 8(%rdi)
+ sbbq %r8, %r10
+ movq 24(%rdx), %r9
+ movq 24(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 16(%rdi)
+ sbbq %r9, %r8
+ movq 32(%rdx), %r10
+ movq 32(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, 24(%rdi)
+ sbbq %r10, %r9
+ movq 40(%rdx), %r8
+ movq 40(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 32(%rdi)
+ sbbq %r8, %r10
+ movq %r10, 40(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_384_cond_sub_avx2_6,.-sp_384_cond_sub_avx2_6
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_div2_avx2_6
+.type sp_384_div2_avx2_6,@function
+.align 16
+sp_384_div2_avx2_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_div2_avx2_6
+.p2align 4
+_sp_384_div2_avx2_6:
+#endif /* __APPLE__ */
+ movq (%rsi), %r11
+ xorq %r10, %r10
+ movq %r11, %r8
+ andq $0x01, %r11
+ negq %r11
+ movq (%rdx), %rax
+ movq 8(%rdx), %rcx
+ movq (%rsi), %r8
+ movq 8(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ addq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq 16(%rdx), %rax
+ movq 24(%rdx), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdx), %rax
+ movq 40(%rdx), %rcx
+ movq 32(%rsi), %r8
+ movq 40(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ adcq $0x00, %r10
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 24(%rdi)
+ movq 40(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 32(%rdi)
+ shrdq $0x01, %r10, %r9
+ movq %r9, 40(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_384_div2_avx2_6,.-sp_384_div2_avx2_6
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#ifndef WC_NO_CACHE_RESISTANT
/* Touch each possible entry that could be being copied.
*
@@ -43946,21 +44713,21 @@ _sp_384_sqr_avx2_6:
*/
#ifndef __APPLE__
.text
-.globl sp_384_get_entry_256_6
-.type sp_384_get_entry_256_6,@function
+.globl sp_384_get_entry_64_6
+.type sp_384_get_entry_64_6,@function
.align 16
-sp_384_get_entry_256_6:
+sp_384_get_entry_64_6:
#else
.section __TEXT,__text
-.globl _sp_384_get_entry_256_6
+.globl _sp_384_get_entry_64_6
.p2align 4
-_sp_384_get_entry_256_6:
+_sp_384_get_entry_64_6:
#endif /* __APPLE__ */
movq $0x01, %rax
movd %edx, %xmm13
addq $0x60, %rsi
movd %eax, %xmm15
- movq $0xff, %rax
+ movq $63, %rax
pshufd $0x00, %xmm15, %xmm15
pshufd $0x00, %xmm13, %xmm13
pxor %xmm14, %xmm14
@@ -43971,7 +44738,7 @@ _sp_384_get_entry_256_6:
pxor %xmm4, %xmm4
pxor %xmm5, %xmm5
movdqa %xmm15, %xmm14
-L_384_get_entry_256_6_start:
+L_384_get_entry_64_6_start:
movdqa %xmm14, %xmm12
paddd %xmm15, %xmm14
pcmpeqd %xmm13, %xmm12
@@ -43995,7 +44762,7 @@ L_384_get_entry_256_6_start:
por %xmm10, %xmm4
por %xmm11, %xmm5
decq %rax
- jnz L_384_get_entry_256_6_start
+ jnz L_384_get_entry_64_6_start
movdqu %xmm0, (%rdi)
movdqu %xmm1, 16(%rdi)
movdqu %xmm2, 32(%rdi)
@@ -44004,8 +44771,9 @@ L_384_get_entry_256_6_start:
movdqu %xmm5, 128(%rdi)
repz retq
#ifndef __APPLE__
-.size sp_384_get_entry_256_6,.-sp_384_get_entry_256_6
+.size sp_384_get_entry_64_6,.-sp_384_get_entry_64_6
#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
/* Touch each possible entry that could be being copied.
*
* r Point to copy into.
@@ -44014,21 +44782,21 @@ L_384_get_entry_256_6_start:
*/
#ifndef __APPLE__
.text
-.globl sp_384_get_entry_256_avx2_6
-.type sp_384_get_entry_256_avx2_6,@function
+.globl sp_384_get_entry_64_avx2_6
+.type sp_384_get_entry_64_avx2_6,@function
.align 16
-sp_384_get_entry_256_avx2_6:
+sp_384_get_entry_64_avx2_6:
#else
.section __TEXT,__text
-.globl _sp_384_get_entry_256_avx2_6
+.globl _sp_384_get_entry_64_avx2_6
.p2align 4
-_sp_384_get_entry_256_avx2_6:
+_sp_384_get_entry_64_avx2_6:
#endif /* __APPLE__ */
movq $0x01, %rax
movd %edx, %xmm9
addq $0x60, %rsi
movd %eax, %xmm11
- movq $0x100, %rax
+ movq $0x40, %rax
vpxor %ymm10, %ymm10, %ymm10
vpermd %ymm9, %ymm10, %ymm9
vpermd %ymm11, %ymm10, %ymm11
@@ -44037,12 +44805,12 @@ _sp_384_get_entry_256_avx2_6:
vpxor %ymm2, %ymm2, %ymm2
vpxor %xmm3, %xmm3, %xmm3
vmovdqa %ymm11, %ymm10
-L_384_get_entry_256_avx2_6_start:
+L_384_get_entry_64_avx2_6_start:
vpcmpeqd %ymm9, %ymm10, %ymm8
vpaddd %ymm11, %ymm10, %ymm10
- vmovdqu (%rsi), %ymm4
+ vmovupd (%rsi), %ymm4
vmovdqu 32(%rsi), %xmm5
- vmovdqu 48(%rsi), %ymm6
+ vmovupd 48(%rsi), %ymm6
vmovdqu 80(%rsi), %xmm7
addq $0x60, %rsi
vpand %ymm8, %ymm4, %ymm4
@@ -44054,15 +44822,145 @@ L_384_get_entry_256_avx2_6_start:
vpor %ymm6, %ymm2, %ymm2
vpor %xmm7, %xmm3, %xmm3
decq %rax
- jnz L_384_get_entry_256_avx2_6_start
- vmovdqu %ymm0, (%rdi)
+ jnz L_384_get_entry_64_avx2_6_start
+ vmovupd %ymm0, (%rdi)
vmovdqu %xmm1, 32(%rdi)
- vmovdqu %ymm2, 96(%rdi)
+ vmovupd %ymm2, 96(%rdi)
vmovdqu %xmm3, 128(%rdi)
repz retq
#ifndef __APPLE__
-.size sp_384_get_entry_256_avx2_6,.-sp_384_get_entry_256_avx2_6
+.size sp_384_get_entry_64_avx2_6,.-sp_384_get_entry_64_avx2_6
#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#endif /* !WC_NO_CACHE_RESISTANT */
+#ifndef WC_NO_CACHE_RESISTANT
+/* Touch each possible entry that could be being copied.
+ *
+ * r Point to copy into.
+ * table Table - start of the entires to access
+ * idx Index of entry to retrieve.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_get_entry_65_6
+.type sp_384_get_entry_65_6,@function
+.align 16
+sp_384_get_entry_65_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_get_entry_65_6
+.p2align 4
+_sp_384_get_entry_65_6:
+#endif /* __APPLE__ */
+ movq $0x01, %rax
+ movd %edx, %xmm13
+ addq $0x60, %rsi
+ movd %eax, %xmm15
+ movq $0x40, %rax
+ pshufd $0x00, %xmm15, %xmm15
+ pshufd $0x00, %xmm13, %xmm13
+ pxor %xmm14, %xmm14
+ pxor %xmm0, %xmm0
+ pxor %xmm1, %xmm1
+ pxor %xmm2, %xmm2
+ pxor %xmm3, %xmm3
+ pxor %xmm4, %xmm4
+ pxor %xmm5, %xmm5
+ movdqa %xmm15, %xmm14
+L_384_get_entry_65_6_start:
+ movdqa %xmm14, %xmm12
+ paddd %xmm15, %xmm14
+ pcmpeqd %xmm13, %xmm12
+ movdqa (%rsi), %xmm6
+ movdqa 16(%rsi), %xmm7
+ movdqa 32(%rsi), %xmm8
+ movdqa 48(%rsi), %xmm9
+ movdqa 64(%rsi), %xmm10
+ movdqa 80(%rsi), %xmm11
+ addq $0x60, %rsi
+ pand %xmm12, %xmm6
+ pand %xmm12, %xmm7
+ pand %xmm12, %xmm8
+ pand %xmm12, %xmm9
+ pand %xmm12, %xmm10
+ pand %xmm12, %xmm11
+ por %xmm6, %xmm0
+ por %xmm7, %xmm1
+ por %xmm8, %xmm2
+ por %xmm9, %xmm3
+ por %xmm10, %xmm4
+ por %xmm11, %xmm5
+ decq %rax
+ jnz L_384_get_entry_65_6_start
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, 32(%rdi)
+ movdqu %xmm3, 96(%rdi)
+ movdqu %xmm4, 112(%rdi)
+ movdqu %xmm5, 128(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_384_get_entry_65_6,.-sp_384_get_entry_65_6
+#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
+/* Touch each possible entry that could be being copied.
+ *
+ * r Point to copy into.
+ * table Table - start of the entires to access
+ * idx Index of entry to retrieve.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_384_get_entry_65_avx2_6
+.type sp_384_get_entry_65_avx2_6,@function
+.align 16
+sp_384_get_entry_65_avx2_6:
+#else
+.section __TEXT,__text
+.globl _sp_384_get_entry_65_avx2_6
+.p2align 4
+_sp_384_get_entry_65_avx2_6:
+#endif /* __APPLE__ */
+ movq $0x01, %rax
+ movd %edx, %xmm9
+ addq $0x60, %rsi
+ movd %eax, %xmm11
+ movq $0x41, %rax
+ vpxor %ymm10, %ymm10, %ymm10
+ vpermd %ymm9, %ymm10, %ymm9
+ vpermd %ymm11, %ymm10, %ymm11
+ vpxor %ymm0, %ymm0, %ymm0
+ vpxor %xmm1, %xmm1, %xmm1
+ vpxor %ymm2, %ymm2, %ymm2
+ vpxor %xmm3, %xmm3, %xmm3
+ vmovdqa %ymm11, %ymm10
+L_384_get_entry_65_avx2_6_start:
+ vpcmpeqd %ymm9, %ymm10, %ymm8
+ vpaddd %ymm11, %ymm10, %ymm10
+ vmovupd (%rsi), %ymm4
+ vmovdqu 32(%rsi), %xmm5
+ vmovupd 48(%rsi), %ymm6
+ vmovdqu 80(%rsi), %xmm7
+ addq $0x60, %rsi
+ vpand %ymm8, %ymm4, %ymm4
+ vpand %xmm8, %xmm5, %xmm5
+ vpand %ymm8, %ymm6, %ymm6
+ vpand %xmm8, %xmm7, %xmm7
+ vpor %ymm4, %ymm0, %ymm0
+ vpor %xmm5, %xmm1, %xmm1
+ vpor %ymm6, %ymm2, %ymm2
+ vpor %xmm7, %xmm3, %xmm3
+ decq %rax
+ jnz L_384_get_entry_65_avx2_6_start
+ vmovupd %ymm0, (%rdi)
+ vmovdqu %xmm1, 32(%rdi)
+ vmovupd %ymm2, 96(%rdi)
+ vmovdqu %xmm3, 128(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_384_get_entry_65_avx2_6,.-sp_384_get_entry_65_avx2_6
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
#endif /* !WC_NO_CACHE_RESISTANT */
/* Add 1 to a. (a = a + 1)
*
@@ -44184,6 +45082,7 @@ L_384_from_bin_bswap_zero_end:
#ifndef __APPLE__
.size sp_384_from_bin_bswap,.-sp_384_from_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Read big endian unsigned byte array into r.
* Uses the movbe instruction which is an optional instruction.
*
@@ -44269,6 +45168,7 @@ L_384_from_bin_movbe_zero_end:
#ifndef __APPLE__
.size sp_384_from_bin_movbe,.-sp_384_from_bin_movbe
#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 48
* Uses the bswap instruction.
@@ -44310,6 +45210,7 @@ _sp_384_to_bin_bswap:
#ifndef __APPLE__
.size sp_384_to_bin_bswap,.-sp_384_to_bin_bswap
#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
/* Write r as big endian to byte array.
* Fixed length number of bytes written: 48
* Uses the movbe instruction which is optional.
@@ -44345,6 +45246,7 @@ _sp_384_to_bin_movbe:
#ifndef __APPLE__
.size sp_384_to_bin_movbe,.-sp_384_to_bin_movbe
#endif /* __APPLE__ */
+#endif /* NO_MOVBE_SUPPORT */
/* Sub b from a into a. (a -= b)
*
* a A single precision integer and result.
@@ -44380,62 +45282,6 @@ _sp_384_sub_in_place_6:
#ifndef __APPLE__
.size sp_384_sub_in_place_6,.-sp_384_sub_in_place_6
#endif /* __APPLE__ */
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
-#ifndef __APPLE__
-.text
-.globl sp_384_cond_sub_avx2_6
-.type sp_384_cond_sub_avx2_6,@function
-.align 16
-sp_384_cond_sub_avx2_6:
-#else
-.section __TEXT,__text
-.globl _sp_384_cond_sub_avx2_6
-.p2align 4
-_sp_384_cond_sub_avx2_6:
-#endif /* __APPLE__ */
- movq $0x00, %rax
- movq (%rdx), %r10
- movq (%rsi), %r8
- pextq %rcx, %r10, %r10
- subq %r10, %r8
- movq 8(%rdx), %r10
- movq 8(%rsi), %r9
- pextq %rcx, %r10, %r10
- movq %r8, (%rdi)
- sbbq %r10, %r9
- movq 16(%rdx), %r8
- movq 16(%rsi), %r10
- pextq %rcx, %r8, %r8
- movq %r9, 8(%rdi)
- sbbq %r8, %r10
- movq 24(%rdx), %r9
- movq 24(%rsi), %r8
- pextq %rcx, %r9, %r9
- movq %r10, 16(%rdi)
- sbbq %r9, %r8
- movq 32(%rdx), %r10
- movq 32(%rsi), %r9
- pextq %rcx, %r10, %r10
- movq %r8, 24(%rdi)
- sbbq %r10, %r9
- movq 40(%rdx), %r8
- movq 40(%rsi), %r10
- pextq %rcx, %r8, %r8
- movq %r9, 32(%rdi)
- sbbq %r8, %r10
- movq %r10, 40(%rdi)
- sbbq $0x00, %rax
- repz retq
-#ifndef __APPLE__
-.size sp_384_cond_sub_avx2_6,.-sp_384_cond_sub_avx2_6
-#endif /* __APPLE__ */
/* Mul a by digit b into r. (r = a * b)
*
* r A single precision integer.
@@ -44534,26 +45380,26 @@ _sp_384_mul_d_avx2_6:
mulxq 8(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 8(%rdi)
adoxq %r8, %r9
+ movq %r10, 8(%rdi)
# A[2] * B
mulxq 16(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 16(%rdi)
adoxq %r8, %r10
+ movq %r9, 16(%rdi)
# A[3] * B
mulxq 24(%rsi), %rcx, %r8
movq %r11, %r9
adcxq %rcx, %r10
- movq %r10, 24(%rdi)
adoxq %r8, %r9
+ movq %r10, 24(%rdi)
# A[4] * B
mulxq 32(%rsi), %rcx, %r8
movq %r11, %r10
adcxq %rcx, %r9
- movq %r9, 32(%rdi)
adoxq %r8, %r10
+ movq %r9, 32(%rdi)
# A[5] * B
mulxq 40(%rsi), %rcx, %r8
movq %r11, %r9
@@ -44567,6 +45413,35 @@ _sp_384_mul_d_avx2_6:
.size sp_384_mul_d_avx2_6,.-sp_384_mul_d_avx2_6
#endif /* __APPLE__ */
#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_384_word_asm_6
+.type div_384_word_asm_6,@function
+.align 16
+div_384_word_asm_6:
+#else
+.section __TEXT,__text
+.globl _div_384_word_asm_6
+.p2align 4
+_div_384_word_asm_6:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_384_word_asm_6,.-div_384_word_asm_6
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
/* Shift number right by 1 bit. (r = a >> 1)
*
* r Result of right shift by 1.
@@ -44743,6 +45618,9133 @@ L_384_num_bits_6_done:
.size sp_384_num_bits_6,.-sp_384_num_bits_6
#endif /* __APPLE__ */
#endif /* WOLFSSL_SP_384 */
+#ifdef WOLFSSL_SP_1024
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mul_16
+.type sp_1024_mul_16,@function
+.align 16
+sp_1024_mul_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mul_16
+.p2align 4
+_sp_1024_mul_16:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ subq $0x80, %rsp
+ # A[0] * B[0]
+ movq (%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ movq %rax, (%rsp)
+ movq %rdx, %r9
+ # A[0] * B[1]
+ movq 8(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[0]
+ movq (%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 8(%rsp)
+ # A[0] * B[2]
+ movq 16(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[1]
+ movq 8(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[0]
+ movq (%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 16(%rsp)
+ # A[0] * B[3]
+ movq 24(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[2]
+ movq 16(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[1]
+ movq 8(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[0]
+ movq (%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 24(%rsp)
+ # A[0] * B[4]
+ movq 32(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[3]
+ movq 24(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[2]
+ movq 16(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[1]
+ movq 8(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[4] * B[0]
+ movq (%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 32(%rsp)
+ # A[0] * B[5]
+ movq 40(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[4]
+ movq 32(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[3]
+ movq 24(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[2]
+ movq 16(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[4] * B[1]
+ movq 8(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[5] * B[0]
+ movq (%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 40(%rsp)
+ # A[0] * B[6]
+ movq 48(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[5]
+ movq 40(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[4]
+ movq 32(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[3]
+ movq 24(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B[2]
+ movq 16(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[5] * B[1]
+ movq 8(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[6] * B[0]
+ movq (%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 48(%rsp)
+ # A[0] * B[7]
+ movq 56(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[6]
+ movq 48(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[5]
+ movq 40(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[4]
+ movq 32(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[4] * B[3]
+ movq 24(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B[2]
+ movq 16(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[6] * B[1]
+ movq 8(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[7] * B[0]
+ movq (%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 56(%rsp)
+ # A[0] * B[8]
+ movq 64(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[7]
+ movq 56(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[6]
+ movq 48(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[5]
+ movq 40(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[4] * B[4]
+ movq 32(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[5] * B[3]
+ movq 24(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B[2]
+ movq 16(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[7] * B[1]
+ movq 8(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[8] * B[0]
+ movq (%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 64(%rsp)
+ # A[0] * B[9]
+ movq 72(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[8]
+ movq 64(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[7]
+ movq 56(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[6]
+ movq 48(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B[5]
+ movq 40(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[5] * B[4]
+ movq 32(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[6] * B[3]
+ movq 24(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B[2]
+ movq 16(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[8] * B[1]
+ movq 8(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[9] * B[0]
+ movq (%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 72(%rsp)
+ # A[0] * B[10]
+ movq 80(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[9]
+ movq 72(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[8]
+ movq 64(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[7]
+ movq 56(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[4] * B[6]
+ movq 48(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B[5]
+ movq 40(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[6] * B[4]
+ movq 32(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[7] * B[3]
+ movq 24(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B[2]
+ movq 16(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[9] * B[1]
+ movq 8(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[10] * B[0]
+ movq (%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 80(%rsp)
+ # A[0] * B[11]
+ movq 88(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[10]
+ movq 80(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[9]
+ movq 72(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[8]
+ movq 64(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[4] * B[7]
+ movq 56(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[5] * B[6]
+ movq 48(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B[5]
+ movq 40(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[7] * B[4]
+ movq 32(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[8] * B[3]
+ movq 24(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B[2]
+ movq 16(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[10] * B[1]
+ movq 8(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[11] * B[0]
+ movq (%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 88(%rsp)
+ # A[0] * B[12]
+ movq 96(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[11]
+ movq 88(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[10]
+ movq 80(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[9]
+ movq 72(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B[8]
+ movq 64(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[5] * B[7]
+ movq 56(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[6] * B[6]
+ movq 48(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B[5]
+ movq 40(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[8] * B[4]
+ movq 32(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[9] * B[3]
+ movq 24(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B[2]
+ movq 16(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[11] * B[1]
+ movq 8(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[12] * B[0]
+ movq (%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 96(%rsp)
+ # A[0] * B[13]
+ movq 104(%rcx), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[1] * B[12]
+ movq 96(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[11]
+ movq 88(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[10]
+ movq 80(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[4] * B[9]
+ movq 72(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B[8]
+ movq 64(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[6] * B[7]
+ movq 56(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[7] * B[6]
+ movq 48(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B[5]
+ movq 40(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[9] * B[4]
+ movq 32(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[10] * B[3]
+ movq 24(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B[2]
+ movq 16(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[12] * B[1]
+ movq 8(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[13] * B[0]
+ movq (%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 104(%rsp)
+ # A[0] * B[14]
+ movq 112(%rcx), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * B[13]
+ movq 104(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[2] * B[12]
+ movq 96(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[11]
+ movq 88(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[4] * B[10]
+ movq 80(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[5] * B[9]
+ movq 72(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B[8]
+ movq 64(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[7] * B[7]
+ movq 56(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[8] * B[6]
+ movq 48(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B[5]
+ movq 40(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[10] * B[4]
+ movq 32(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[11] * B[3]
+ movq 24(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B[2]
+ movq 16(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * B[1]
+ movq 8(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[14] * B[0]
+ movq (%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 112(%rsp)
+ # A[0] * B[15]
+ movq 120(%rcx), %rax
+ mulq (%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[1] * B[14]
+ movq 112(%rcx), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[2] * B[13]
+ movq 104(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[3] * B[12]
+ movq 96(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B[11]
+ movq 88(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[5] * B[10]
+ movq 80(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[6] * B[9]
+ movq 72(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B[8]
+ movq 64(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[8] * B[7]
+ movq 56(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[9] * B[6]
+ movq 48(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B[5]
+ movq 40(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[11] * B[4]
+ movq 32(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[12] * B[3]
+ movq 24(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B[2]
+ movq 16(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[14] * B[1]
+ movq 8(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[15] * B[0]
+ movq (%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 120(%rsp)
+ # A[1] * B[15]
+ movq 120(%rcx), %rax
+ mulq 8(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B[14]
+ movq 112(%rcx), %rax
+ mulq 16(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[3] * B[13]
+ movq 104(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[4] * B[12]
+ movq 96(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B[11]
+ movq 88(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[6] * B[10]
+ movq 80(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[7] * B[9]
+ movq 72(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B[8]
+ movq 64(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[9] * B[7]
+ movq 56(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[10] * B[6]
+ movq 48(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B[5]
+ movq 40(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[12] * B[4]
+ movq 32(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[13] * B[3]
+ movq 24(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B[2]
+ movq 16(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[15] * B[1]
+ movq 8(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 128(%rdi)
+ # A[2] * B[15]
+ movq 120(%rcx), %rax
+ mulq 16(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B[14]
+ movq 112(%rcx), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[4] * B[13]
+ movq 104(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[5] * B[12]
+ movq 96(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B[11]
+ movq 88(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[7] * B[10]
+ movq 80(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[8] * B[9]
+ movq 72(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B[8]
+ movq 64(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[10] * B[7]
+ movq 56(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[11] * B[6]
+ movq 48(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B[5]
+ movq 40(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * B[4]
+ movq 32(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[14] * B[3]
+ movq 24(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B[2]
+ movq 16(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 136(%rdi)
+ # A[3] * B[15]
+ movq 120(%rcx), %rax
+ mulq 24(%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B[14]
+ movq 112(%rcx), %rax
+ mulq 32(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[5] * B[13]
+ movq 104(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[6] * B[12]
+ movq 96(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B[11]
+ movq 88(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[8] * B[10]
+ movq 80(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[9] * B[9]
+ movq 72(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B[8]
+ movq 64(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[11] * B[7]
+ movq 56(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[12] * B[6]
+ movq 48(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B[5]
+ movq 40(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[14] * B[4]
+ movq 32(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[15] * B[3]
+ movq 24(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 144(%rdi)
+ # A[4] * B[15]
+ movq 120(%rcx), %rax
+ mulq 32(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B[14]
+ movq 112(%rcx), %rax
+ mulq 40(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[6] * B[13]
+ movq 104(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[7] * B[12]
+ movq 96(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B[11]
+ movq 88(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[9] * B[10]
+ movq 80(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[10] * B[9]
+ movq 72(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B[8]
+ movq 64(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[12] * B[7]
+ movq 56(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[13] * B[6]
+ movq 48(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B[5]
+ movq 40(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[15] * B[4]
+ movq 32(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 152(%rdi)
+ # A[5] * B[15]
+ movq 120(%rcx), %rax
+ mulq 40(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B[14]
+ movq 112(%rcx), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[7] * B[13]
+ movq 104(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[8] * B[12]
+ movq 96(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B[11]
+ movq 88(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[10] * B[10]
+ movq 80(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[11] * B[9]
+ movq 72(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B[8]
+ movq 64(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * B[7]
+ movq 56(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[14] * B[6]
+ movq 48(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B[5]
+ movq 40(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 160(%rdi)
+ # A[6] * B[15]
+ movq 120(%rcx), %rax
+ mulq 48(%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B[14]
+ movq 112(%rcx), %rax
+ mulq 56(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[8] * B[13]
+ movq 104(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[9] * B[12]
+ movq 96(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B[11]
+ movq 88(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[11] * B[10]
+ movq 80(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[12] * B[9]
+ movq 72(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B[8]
+ movq 64(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[14] * B[7]
+ movq 56(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[15] * B[6]
+ movq 48(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 168(%rdi)
+ # A[7] * B[15]
+ movq 120(%rcx), %rax
+ mulq 56(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B[14]
+ movq 112(%rcx), %rax
+ mulq 64(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[9] * B[13]
+ movq 104(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[10] * B[12]
+ movq 96(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B[11]
+ movq 88(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[12] * B[10]
+ movq 80(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[13] * B[9]
+ movq 72(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B[8]
+ movq 64(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[15] * B[7]
+ movq 56(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 176(%rdi)
+ # A[8] * B[15]
+ movq 120(%rcx), %rax
+ mulq 64(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B[14]
+ movq 112(%rcx), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[10] * B[13]
+ movq 104(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[11] * B[12]
+ movq 96(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B[11]
+ movq 88(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * B[10]
+ movq 80(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[14] * B[9]
+ movq 72(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B[8]
+ movq 64(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 184(%rdi)
+ # A[9] * B[15]
+ movq 120(%rcx), %rax
+ mulq 72(%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B[14]
+ movq 112(%rcx), %rax
+ mulq 80(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[11] * B[13]
+ movq 104(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[12] * B[12]
+ movq 96(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B[11]
+ movq 88(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[14] * B[10]
+ movq 80(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[15] * B[9]
+ movq 72(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 192(%rdi)
+ # A[10] * B[15]
+ movq 120(%rcx), %rax
+ mulq 80(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B[14]
+ movq 112(%rcx), %rax
+ mulq 88(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[12] * B[13]
+ movq 104(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[13] * B[12]
+ movq 96(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B[11]
+ movq 88(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[15] * B[10]
+ movq 80(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 200(%rdi)
+ # A[11] * B[15]
+ movq 120(%rcx), %rax
+ mulq 88(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B[14]
+ movq 112(%rcx), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * B[13]
+ movq 104(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[14] * B[12]
+ movq 96(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B[11]
+ movq 88(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 208(%rdi)
+ # A[12] * B[15]
+ movq 120(%rcx), %rax
+ mulq 96(%rsi)
+ xorq %r10, %r10
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B[14]
+ movq 112(%rcx), %rax
+ mulq 104(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[14] * B[13]
+ movq 104(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[15] * B[12]
+ movq 96(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ movq %r8, 216(%rdi)
+ # A[13] * B[15]
+ movq 120(%rcx), %rax
+ mulq 104(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B[14]
+ movq 112(%rcx), %rax
+ mulq 112(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[15] * B[13]
+ movq 104(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ movq %r9, 224(%rdi)
+ # A[14] * B[15]
+ movq 120(%rcx), %rax
+ mulq 112(%rsi)
+ xorq %r9, %r9
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B[14]
+ movq 112(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %r10, 232(%rdi)
+ # A[15] * B[15]
+ movq 120(%rcx), %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ movq %r8, 240(%rdi)
+ movq %r9, 248(%rdi)
+ movq (%rsp), %rax
+ movq 8(%rsp), %rdx
+ movq 16(%rsp), %r8
+ movq 24(%rsp), %r9
+ movq %rax, (%rdi)
+ movq %rdx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rsp), %rax
+ movq 40(%rsp), %rdx
+ movq 48(%rsp), %r8
+ movq 56(%rsp), %r9
+ movq %rax, 32(%rdi)
+ movq %rdx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rsp), %rax
+ movq 72(%rsp), %rdx
+ movq 80(%rsp), %r8
+ movq 88(%rsp), %r9
+ movq %rax, 64(%rdi)
+ movq %rdx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rsp), %rax
+ movq 104(%rsp), %rdx
+ movq 112(%rsp), %r8
+ movq 120(%rsp), %r9
+ movq %rax, 96(%rdi)
+ movq %rdx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mul_16,.-sp_1024_mul_16
+#endif /* __APPLE__ */
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_sqr_16
+.type sp_1024_sqr_16,@function
+.align 16
+sp_1024_sqr_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_sqr_16
+.p2align 4
+_sp_1024_sqr_16:
+#endif /* __APPLE__ */
+ pushq %r12
+ subq $0x80, %rsp
+ # A[0] * A[0]
+ movq (%rsi), %rax
+ mulq %rax
+ xorq %r9, %r9
+ movq %rax, (%rsp)
+ movq %rdx, %r8
+ # A[0] * A[1]
+ movq 8(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ movq %r8, 8(%rsp)
+ # A[0] * A[2]
+ movq 16(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ # A[1] * A[1]
+ movq 8(%rsi), %rax
+ mulq %rax
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ movq %r9, 16(%rsp)
+ # A[0] * A[3]
+ movq 24(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[1] * A[2]
+ movq 16(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %rcx, 24(%rsp)
+ # A[0] * A[4]
+ movq 32(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ # A[1] * A[3]
+ movq 24(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ # A[2] * A[2]
+ movq 16(%rsi), %rax
+ mulq %rax
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ movq %r8, 32(%rsp)
+ # A[0] * A[5]
+ movq 40(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[4]
+ movq 32(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[3]
+ movq 24(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 40(%rsp)
+ # A[0] * A[6]
+ movq 48(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[5]
+ movq 40(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[4]
+ movq 32(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[3]
+ movq 24(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 48(%rsp)
+ # A[0] * A[7]
+ movq 56(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[6]
+ movq 48(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[5]
+ movq 40(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[4]
+ movq 32(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 56(%rsp)
+ # A[0] * A[8]
+ movq 64(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[7]
+ movq 56(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[6]
+ movq 48(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[5]
+ movq 40(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[4]
+ movq 32(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 64(%rsp)
+ # A[0] * A[9]
+ movq 72(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[8]
+ movq 64(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[7]
+ movq 56(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[6]
+ movq 48(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[5]
+ movq 40(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 72(%rsp)
+ # A[0] * A[10]
+ movq 80(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[9]
+ movq 72(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[8]
+ movq 64(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[7]
+ movq 56(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[6]
+ movq 48(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[5]
+ movq 40(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 80(%rsp)
+ # A[0] * A[11]
+ movq 88(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[10]
+ movq 80(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[9]
+ movq 72(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[8]
+ movq 64(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[7]
+ movq 56(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[6]
+ movq 48(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 88(%rsp)
+ # A[0] * A[12]
+ movq 96(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[11]
+ movq 88(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[10]
+ movq 80(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[9]
+ movq 72(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[8]
+ movq 64(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[7]
+ movq 56(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[6]
+ movq 48(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 96(%rsp)
+ # A[0] * A[13]
+ movq 104(%rsi), %rax
+ mulq (%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[12]
+ movq 96(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[11]
+ movq 88(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[10]
+ movq 80(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[9]
+ movq 72(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[8]
+ movq 64(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[7]
+ movq 56(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 104(%rsp)
+ # A[0] * A[14]
+ movq 112(%rsi), %rax
+ mulq (%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[13]
+ movq 104(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[12]
+ movq 96(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[11]
+ movq 88(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[10]
+ movq 80(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[9]
+ movq 72(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[8]
+ movq 64(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[7]
+ movq 56(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 112(%rsp)
+ # A[0] * A[15]
+ movq 120(%rsi), %rax
+ mulq (%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[1] * A[14]
+ movq 112(%rsi), %rax
+ mulq 8(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[2] * A[13]
+ movq 104(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[12]
+ movq 96(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[11]
+ movq 88(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[10]
+ movq 80(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[9]
+ movq 72(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[8]
+ movq 64(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 120(%rsp)
+ # A[1] * A[15]
+ movq 120(%rsi), %rax
+ mulq 8(%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[2] * A[14]
+ movq 112(%rsi), %rax
+ mulq 16(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[3] * A[13]
+ movq 104(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[12]
+ movq 96(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[11]
+ movq 88(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[10]
+ movq 80(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[9]
+ movq 72(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[8]
+ movq 64(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 128(%rdi)
+ # A[2] * A[15]
+ movq 120(%rsi), %rax
+ mulq 16(%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[3] * A[14]
+ movq 112(%rsi), %rax
+ mulq 24(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[4] * A[13]
+ movq 104(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[12]
+ movq 96(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[11]
+ movq 88(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[10]
+ movq 80(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[9]
+ movq 72(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 136(%rdi)
+ # A[3] * A[15]
+ movq 120(%rsi), %rax
+ mulq 24(%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[4] * A[14]
+ movq 112(%rsi), %rax
+ mulq 32(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[5] * A[13]
+ movq 104(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[12]
+ movq 96(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[11]
+ movq 88(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[10]
+ movq 80(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[9] * A[9]
+ movq 72(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 144(%rdi)
+ # A[4] * A[15]
+ movq 120(%rsi), %rax
+ mulq 32(%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[5] * A[14]
+ movq 112(%rsi), %rax
+ mulq 40(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[6] * A[13]
+ movq 104(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[12]
+ movq 96(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[11]
+ movq 88(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[9] * A[10]
+ movq 80(%rsi), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 152(%rdi)
+ # A[5] * A[15]
+ movq 120(%rsi), %rax
+ mulq 40(%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[6] * A[14]
+ movq 112(%rsi), %rax
+ mulq 48(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[7] * A[13]
+ movq 104(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[12]
+ movq 96(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[9] * A[11]
+ movq 88(%rsi), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[10] * A[10]
+ movq 80(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 160(%rdi)
+ # A[6] * A[15]
+ movq 120(%rsi), %rax
+ mulq 48(%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[7] * A[14]
+ movq 112(%rsi), %rax
+ mulq 56(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[8] * A[13]
+ movq 104(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[9] * A[12]
+ movq 96(%rsi), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[10] * A[11]
+ movq 88(%rsi), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 168(%rdi)
+ # A[7] * A[15]
+ movq 120(%rsi), %rax
+ mulq 56(%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[8] * A[14]
+ movq 112(%rsi), %rax
+ mulq 64(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[9] * A[13]
+ movq 104(%rsi), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[10] * A[12]
+ movq 96(%rsi), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[11] * A[11]
+ movq 88(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 176(%rdi)
+ # A[8] * A[15]
+ movq 120(%rsi), %rax
+ mulq 64(%rsi)
+ xorq %r8, %r8
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[9] * A[14]
+ movq 112(%rsi), %rax
+ mulq 72(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[10] * A[13]
+ movq 104(%rsi), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[11] * A[12]
+ movq 96(%rsi), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r9
+ adcq %r11, %rcx
+ adcq %r12, %r8
+ movq %r9, 184(%rdi)
+ # A[9] * A[15]
+ movq 120(%rsi), %rax
+ mulq 72(%rsi)
+ xorq %r9, %r9
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[10] * A[14]
+ movq 112(%rsi), %rax
+ mulq 80(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[11] * A[13]
+ movq 104(%rsi), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[12] * A[12]
+ movq 96(%rsi), %rax
+ mulq %rax
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %rcx
+ adcq %r11, %r8
+ adcq %r12, %r9
+ movq %rcx, 192(%rdi)
+ # A[10] * A[15]
+ movq 120(%rsi), %rax
+ mulq 80(%rsi)
+ xorq %rcx, %rcx
+ xorq %r12, %r12
+ movq %rax, %r10
+ movq %rdx, %r11
+ # A[11] * A[14]
+ movq 112(%rsi), %rax
+ mulq 88(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ # A[12] * A[13]
+ movq 104(%rsi), %rax
+ mulq 96(%rsi)
+ addq %rax, %r10
+ adcq %rdx, %r11
+ adcq $0x00, %r12
+ addq %r10, %r10
+ adcq %r11, %r11
+ adcq %r12, %r12
+ addq %r10, %r8
+ adcq %r11, %r9
+ adcq %r12, %rcx
+ movq %r8, 200(%rdi)
+ # A[11] * A[15]
+ movq 120(%rsi), %rax
+ mulq 88(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ # A[12] * A[14]
+ movq 112(%rsi), %rax
+ mulq 96(%rsi)
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ # A[13] * A[13]
+ movq 104(%rsi), %rax
+ mulq %rax
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ movq %r9, 208(%rdi)
+ # A[12] * A[15]
+ movq 120(%rsi), %rax
+ mulq 96(%rsi)
+ xorq %r9, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[13] * A[14]
+ movq 112(%rsi), %rax
+ mulq 104(%rsi)
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ movq %rcx, 216(%rdi)
+ # A[13] * A[15]
+ movq 120(%rsi), %rax
+ mulq 104(%rsi)
+ xorq %rcx, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ # A[14] * A[14]
+ movq 112(%rsi), %rax
+ mulq %rax
+ addq %rax, %r8
+ adcq %rdx, %r9
+ adcq $0x00, %rcx
+ movq %r8, 224(%rdi)
+ # A[14] * A[15]
+ movq 120(%rsi), %rax
+ mulq 112(%rsi)
+ xorq %r8, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ addq %rax, %r9
+ adcq %rdx, %rcx
+ adcq $0x00, %r8
+ movq %r9, 232(%rdi)
+ # A[15] * A[15]
+ movq 120(%rsi), %rax
+ mulq %rax
+ addq %rax, %rcx
+ adcq %rdx, %r8
+ movq %rcx, 240(%rdi)
+ movq %r8, 248(%rdi)
+ movq (%rsp), %rax
+ movq 8(%rsp), %rdx
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq %rax, (%rdi)
+ movq %rdx, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq %r11, 24(%rdi)
+ movq 32(%rsp), %rax
+ movq 40(%rsp), %rdx
+ movq 48(%rsp), %r10
+ movq 56(%rsp), %r11
+ movq %rax, 32(%rdi)
+ movq %rdx, 40(%rdi)
+ movq %r10, 48(%rdi)
+ movq %r11, 56(%rdi)
+ movq 64(%rsp), %rax
+ movq 72(%rsp), %rdx
+ movq 80(%rsp), %r10
+ movq 88(%rsp), %r11
+ movq %rax, 64(%rdi)
+ movq %rdx, 72(%rdi)
+ movq %r10, 80(%rdi)
+ movq %r11, 88(%rdi)
+ movq 96(%rsp), %rax
+ movq 104(%rsp), %rdx
+ movq 112(%rsp), %r10
+ movq 120(%rsp), %r11
+ movq %rax, 96(%rdi)
+ movq %rdx, 104(%rdi)
+ movq %r10, 112(%rdi)
+ movq %r11, 120(%rdi)
+ addq $0x80, %rsp
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_sqr_16,.-sp_1024_sqr_16
+#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
+/* Multiply a and b into r. (r = a * b)
+ *
+ * r Result of multiplication.
+ * a First number to multiply.
+ * b Second number to multiply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mul_avx2_16
+.type sp_1024_mul_avx2_16,@function
+.align 16
+sp_1024_mul_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mul_avx2_16
+.p2align 4
+_sp_1024_mul_avx2_16:
+#endif /* __APPLE__ */
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ movq %rdx, %rbp
+ subq $0x80, %rsp
+ cmpq %rdi, %rsi
+ movq %rsp, %rbx
+ cmovne %rdi, %rbx
+ cmpq %rdi, %rbp
+ cmove %rsp, %rbx
+ addq $0x80, %rdi
+ xorq %r14, %r14
+ movq (%rsi), %rdx
+ # A[0] * B[0]
+ mulx (%rbp), %r8, %r9
+ # A[0] * B[1]
+ mulx 8(%rbp), %rax, %r10
+ movq %r8, (%rbx)
+ adcxq %rax, %r9
+ # A[0] * B[2]
+ mulx 16(%rbp), %rax, %r11
+ movq %r9, 8(%rbx)
+ adcxq %rax, %r10
+ # A[0] * B[3]
+ mulx 24(%rbp), %rax, %r12
+ movq %r10, 16(%rbx)
+ adcxq %rax, %r11
+ movq %r11, 24(%rbx)
+ # A[0] * B[4]
+ mulx 32(%rbp), %rax, %r8
+ adcxq %rax, %r12
+ # A[0] * B[5]
+ mulx 40(%rbp), %rax, %r9
+ movq %r12, 32(%rbx)
+ adcxq %rax, %r8
+ # A[0] * B[6]
+ mulx 48(%rbp), %rax, %r10
+ movq %r8, 40(%rbx)
+ adcxq %rax, %r9
+ # A[0] * B[7]
+ mulx 56(%rbp), %rax, %r11
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ movq %r10, 56(%rbx)
+ # A[0] * B[8]
+ mulx 64(%rbp), %rax, %r12
+ adcxq %rax, %r11
+ # A[0] * B[9]
+ mulx 72(%rbp), %rax, %r8
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ # A[0] * B[10]
+ mulx 80(%rbp), %rax, %r9
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ # A[0] * B[11]
+ mulx 88(%rbp), %rax, %r10
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ movq %r9, 88(%rbx)
+ # A[0] * B[12]
+ mulx 96(%rbp), %rax, %r11
+ adcxq %rax, %r10
+ # A[0] * B[13]
+ mulx 104(%rbp), %rax, %r12
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ # A[0] * B[14]
+ mulx 112(%rbp), %rax, %r8
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ # A[0] * B[15]
+ mulx 120(%rbp), %rax, %r9
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adcxq %r14, %r9
+ movq %r14, %r13
+ adcxq %r14, %r13
+ movq %r8, 120(%rbx)
+ movq %r9, (%rdi)
+ movq 8(%rsi), %rdx
+ movq 8(%rbx), %r9
+ movq 16(%rbx), %r10
+ movq 24(%rbx), %r11
+ movq 32(%rbx), %r12
+ movq 40(%rbx), %r8
+ # A[1] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[1] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r9, 8(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[1] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r10, 16(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[1] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r11, 24(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 32(%rbx)
+ movq 48(%rbx), %r9
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ # A[1] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[1] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r8, 40(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[1] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[1] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 64(%rbx)
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ # A[1] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[1] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[1] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[1] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 96(%rbx)
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ # A[1] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[1] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[1] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[1] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ movq %r14, %r10
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ adcxq %r13, %r10
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r9, (%rdi)
+ movq %r10, 8(%rdi)
+ movq 16(%rsi), %rdx
+ movq 16(%rbx), %r10
+ movq 24(%rbx), %r11
+ movq 32(%rbx), %r12
+ movq 40(%rbx), %r8
+ movq 48(%rbx), %r9
+ # A[2] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[2] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r10, 16(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[2] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r11, 24(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[2] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r12, 32(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 40(%rbx)
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ # A[2] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[2] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[2] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[2] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 72(%rbx)
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ # A[2] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[2] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[2] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[2] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 104(%rbx)
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[2] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[2] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[2] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[2] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ movq %r14, %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ adcxq %r13, %r11
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r10, 8(%rdi)
+ movq %r11, 16(%rdi)
+ movq 24(%rsi), %rdx
+ movq 24(%rbx), %r11
+ movq 32(%rbx), %r12
+ movq 40(%rbx), %r8
+ movq 48(%rbx), %r9
+ movq 56(%rbx), %r10
+ # A[3] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[3] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r11, 24(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[3] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r12, 32(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[3] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r8, 40(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 48(%rbx)
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ # A[3] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[3] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[3] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[3] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 80(%rbx)
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ # A[3] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[3] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[3] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[3] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 112(%rbx)
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ # A[3] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[3] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[3] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[3] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ movq %r14, %r12
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ adcxq %r13, %r12
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r11, 16(%rdi)
+ movq %r12, 24(%rdi)
+ movq 32(%rsi), %rdx
+ movq 32(%rbx), %r12
+ movq 40(%rbx), %r8
+ movq 48(%rbx), %r9
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ # A[4] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[4] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r12, 32(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[4] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r8, 40(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[4] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 56(%rbx)
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ # A[4] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[4] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[4] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[4] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 88(%rbx)
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ # A[4] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[4] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[4] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[4] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 120(%rbx)
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ # A[4] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[4] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[4] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[4] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ movq %r14, %r8
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ adcxq %r13, %r8
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r12, 24(%rdi)
+ movq %r8, 32(%rdi)
+ movq 40(%rsi), %rdx
+ movq 40(%rbx), %r8
+ movq 48(%rbx), %r9
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ # A[5] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[5] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r8, 40(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[5] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[5] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 64(%rbx)
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ # A[5] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[5] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[5] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[5] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 96(%rbx)
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[5] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[5] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[5] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[5] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ # A[5] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[5] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[5] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[5] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ movq %r14, %r9
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ adcxq %r13, %r9
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ movq 48(%rsi), %rdx
+ movq 48(%rbx), %r9
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ # A[6] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[6] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r9, 48(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[6] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[6] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 72(%rbx)
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ # A[6] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[6] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[6] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[6] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 104(%rbx)
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ # A[6] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[6] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[6] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[6] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ # A[6] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[6] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[6] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[6] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ movq %r14, %r10
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ adcxq %r13, %r10
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r9, 40(%rdi)
+ movq %r10, 48(%rdi)
+ movq 56(%rsi), %rdx
+ movq 56(%rbx), %r10
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ # A[7] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[7] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r10, 56(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[7] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[7] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 80(%rbx)
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ # A[7] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[7] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[7] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[7] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 112(%rbx)
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ # A[7] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[7] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[7] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[7] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ # A[7] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[7] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[7] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[7] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ movq %r14, %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ adcxq %r13, %r11
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r10, 48(%rdi)
+ movq %r11, 56(%rdi)
+ movq 64(%rsi), %rdx
+ movq 64(%rbx), %r11
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ # A[8] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[8] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r11, 64(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[8] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[8] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 88(%rbx)
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ # A[8] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[8] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[8] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[8] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 120(%rbx)
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ # A[8] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[8] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[8] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[8] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 24(%rdi)
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ # A[8] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[8] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[8] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[8] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ movq %r14, %r12
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ adcxq %r13, %r12
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r11, 56(%rdi)
+ movq %r12, 64(%rdi)
+ movq 72(%rsi), %rdx
+ movq 72(%rbx), %r12
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ # A[9] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[9] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r12, 72(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[9] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[9] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 96(%rbx)
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[9] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[9] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[9] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[9] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ # A[9] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[9] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[9] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[9] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ # A[9] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[9] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[9] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[9] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ movq %r14, %r8
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ adcxq %r13, %r8
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r12, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq 80(%rsi), %rdx
+ movq 80(%rbx), %r8
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ # A[10] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[10] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r8, 80(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[10] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[10] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 104(%rbx)
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ # A[10] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[10] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[10] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[10] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ # A[10] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[10] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[10] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[10] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ # A[10] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[10] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[10] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[10] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r12, 64(%rdi)
+ movq %r14, %r9
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ adcxq %r13, %r9
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq 88(%rsi), %rdx
+ movq 88(%rbx), %r9
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ # A[11] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[11] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r9, 88(%rbx)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[11] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[11] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 112(%rbx)
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ # A[11] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[11] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[11] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[11] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ # A[11] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[11] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[11] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[11] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ # A[11] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[11] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[11] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r12, 64(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[11] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r8, 72(%rdi)
+ movq %r14, %r10
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ adcxq %r13, %r10
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ movq 96(%rsi), %rdx
+ movq 96(%rbx), %r10
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ # A[12] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[12] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r10, 96(%rbx)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[12] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[12] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 120(%rbx)
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ # A[12] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[12] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[12] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[12] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 24(%rdi)
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ # A[12] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[12] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[12] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[12] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 56(%rdi)
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
+ # A[12] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[12] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r12, 64(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[12] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r8, 72(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[12] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r9, 80(%rdi)
+ movq %r14, %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ adcxq %r13, %r11
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r10, 88(%rdi)
+ movq %r11, 96(%rdi)
+ movq 104(%rsi), %rdx
+ movq 104(%rbx), %r11
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[13] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[13] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r11, 104(%rbx)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[13] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[13] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ # A[13] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[13] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[13] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[13] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ # A[13] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[13] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[13] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[13] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ movq %r12, 64(%rdi)
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
+ movq 96(%rdi), %r11
+ # A[13] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[13] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r8, 72(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[13] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r9, 80(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[13] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r10, 88(%rdi)
+ movq %r14, %r12
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ adcxq %r13, %r12
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r11, 96(%rdi)
+ movq %r12, 104(%rdi)
+ movq 112(%rsi), %rdx
+ movq 112(%rbx), %r12
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ # A[14] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[14] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r12, 112(%rbx)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[14] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 8(%rdi)
+ movq 24(%rdi), %r12
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ # A[14] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[14] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r11, 16(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[14] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r11
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ # A[14] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[14] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r10, 48(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[14] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[14] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r12, 64(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r8, 72(%rdi)
+ movq 88(%rdi), %r10
+ movq 96(%rdi), %r11
+ movq 104(%rdi), %r12
+ # A[14] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[14] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r9, 80(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[14] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r10, 88(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[14] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r11, 96(%rdi)
+ movq %r14, %r8
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ adcxq %r13, %r8
+ movq %r14, %r13
+ adoxq %r14, %r13
+ adcxq %r14, %r13
+ movq %r12, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq 120(%rsi), %rdx
+ movq 120(%rbx), %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ movq 16(%rdi), %r11
+ movq 24(%rdi), %r12
+ # A[15] * B[0]
+ mulx (%rbp), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[15] * B[1]
+ mulx 8(%rbp), %rax, %rcx
+ movq %r8, 120(%rbx)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[15] * B[2]
+ mulx 16(%rbp), %rax, %rcx
+ movq %r9, (%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[15] * B[3]
+ mulx 24(%rbp), %rax, %rcx
+ movq %r10, 8(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ movq %r11, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r11
+ # A[15] * B[4]
+ mulx 32(%rbp), %rax, %rcx
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[15] * B[5]
+ mulx 40(%rbp), %rax, %rcx
+ movq %r12, 24(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[15] * B[6]
+ mulx 48(%rbp), %rax, %rcx
+ movq %r8, 32(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[15] * B[7]
+ mulx 56(%rbp), %rax, %rcx
+ movq %r9, 40(%rdi)
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r12
+ movq 72(%rdi), %r8
+ movq 80(%rdi), %r9
+ movq 88(%rdi), %r10
+ # A[15] * B[8]
+ mulx 64(%rbp), %rax, %rcx
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[15] * B[9]
+ mulx 72(%rbp), %rax, %rcx
+ movq %r11, 56(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[15] * B[10]
+ mulx 80(%rbp), %rax, %rcx
+ movq %r12, 64(%rdi)
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[15] * B[11]
+ mulx 88(%rbp), %rax, %rcx
+ movq %r8, 72(%rdi)
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r9, 80(%rdi)
+ movq 96(%rdi), %r11
+ movq 104(%rdi), %r12
+ movq 112(%rdi), %r8
+ # A[15] * B[12]
+ mulx 96(%rbp), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ # A[15] * B[13]
+ mulx 104(%rbp), %rax, %rcx
+ movq %r10, 88(%rdi)
+ adcxq %rax, %r11
+ adoxq %rcx, %r12
+ # A[15] * B[14]
+ mulx 112(%rbp), %rax, %rcx
+ movq %r11, 96(%rdi)
+ adcxq %rax, %r12
+ adoxq %rcx, %r8
+ # A[15] * B[15]
+ mulx 120(%rbp), %rax, %rcx
+ movq %r12, 104(%rdi)
+ movq %r14, %r9
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ adcxq %r13, %r9
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ subq $0x80, %rdi
+ cmpq %rdi, %rsi
+ je L_start_1024_mul_avx2_16
+ cmpq %rdi, %rbp
+ jne L_end_1024_mul_avx2_16
+L_start_1024_mul_avx2_16:
+ vmovdqu (%rbx), %xmm0
+ vmovups %xmm0, (%rdi)
+ vmovdqu 16(%rbx), %xmm0
+ vmovups %xmm0, 16(%rdi)
+ vmovdqu 32(%rbx), %xmm0
+ vmovups %xmm0, 32(%rdi)
+ vmovdqu 48(%rbx), %xmm0
+ vmovups %xmm0, 48(%rdi)
+ vmovdqu 64(%rbx), %xmm0
+ vmovups %xmm0, 64(%rdi)
+ vmovdqu 80(%rbx), %xmm0
+ vmovups %xmm0, 80(%rdi)
+ vmovdqu 96(%rbx), %xmm0
+ vmovups %xmm0, 96(%rdi)
+ vmovdqu 112(%rbx), %xmm0
+ vmovups %xmm0, 112(%rdi)
+L_end_1024_mul_avx2_16:
+ addq $0x80, %rsp
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ popq %rbx
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mul_avx2_16,.-sp_1024_mul_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Square a and put result in r. (r = a * a)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_sqr_avx2_16
+.type sp_1024_sqr_avx2_16,@function
+.align 16
+sp_1024_sqr_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_sqr_avx2_16
+.p2align 4
+_sp_1024_sqr_avx2_16:
+#endif /* __APPLE__ */
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq %rbx
+ subq $0x80, %rsp
+ cmpq %rdi, %rsi
+ movq %rsp, %rbp
+ cmovne %rdi, %rbp
+ addq $0x80, %rdi
+ xorq %r11, %r11
+ # Diagonal 1
+ xorq %r10, %r10
+ # A[1] x A[0]
+ movq (%rsi), %rdx
+ mulxq 8(%rsi), %r8, %r9
+ # A[2] x A[0]
+ mulxq 16(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 8(%rbp)
+ movq %r9, 16(%rbp)
+ movq %r11, %r8
+ movq %r11, %r9
+ # A[3] x A[0]
+ mulxq 24(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[4] x A[0]
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 24(%rbp)
+ movq %r8, 32(%rbp)
+ movq %r11, %r10
+ movq %r11, %r8
+ # A[5] x A[0]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[6] x A[0]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 40(%rbp)
+ movq %r10, 48(%rbp)
+ movq %r11, %r9
+ movq %r11, %r10
+ # A[7] x A[0]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[8] x A[0]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 56(%rbp)
+ movq %r9, 64(%rbp)
+ movq %r11, %r8
+ movq %r11, %r9
+ # A[9] x A[0]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[10] x A[0]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 72(%rbp)
+ movq %r8, 80(%rbp)
+ movq %r11, %r10
+ movq %r11, %r8
+ # A[11] x A[0]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[12] x A[0]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 88(%rbp)
+ movq %r10, %r13
+ movq %r11, %r9
+ movq %r11, %r10
+ # A[13] x A[0]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] x A[0]
+ mulxq 112(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, %r14
+ movq %r9, %r15
+ movq %r11, %r8
+ # A[15] x A[0]
+ mulxq 120(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, %rbx
+ # Carry
+ adcxq %r11, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, (%rdi)
+ # Diagonal 2
+ movq 24(%rbp), %r8
+ movq 32(%rbp), %r9
+ movq 40(%rbp), %r10
+ # A[2] x A[1]
+ movq 8(%rsi), %rdx
+ mulxq 16(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[3] x A[1]
+ mulxq 24(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 24(%rbp)
+ movq %r9, 32(%rbp)
+ movq 48(%rbp), %r8
+ movq 56(%rbp), %r9
+ # A[4] x A[1]
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[5] x A[1]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 40(%rbp)
+ movq %r8, 48(%rbp)
+ movq 64(%rbp), %r10
+ movq 72(%rbp), %r8
+ # A[6] x A[1]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[7] x A[1]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 56(%rbp)
+ movq %r10, 64(%rbp)
+ movq 80(%rbp), %r9
+ movq 88(%rbp), %r10
+ # A[8] x A[1]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[9] x A[1]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 72(%rbp)
+ movq %r9, 80(%rbp)
+ # No load %r13 - %r8
+ # No load %r14 - %r9
+ # A[10] x A[1]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r13
+ # A[11] x A[1]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ movq %r10, 88(%rbp)
+ # No store %r13
+ # No load %r15 - %r10
+ # No load %rbx - %r8
+ # A[12] x A[1]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[13] x A[1]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r9
+ movq %r11, %r10
+ # A[14] x A[1]
+ mulxq 112(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r9
+ # A[15] x A[1]
+ mulxq 120(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # No store %rbx
+ movq %r9, (%rdi)
+ movq %r11, %r8
+ # A[15] x A[2]
+ movq 16(%rsi), %rdx
+ mulxq 120(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 8(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 16(%rdi)
+ # Diagonal 3
+ movq 40(%rbp), %r8
+ movq 48(%rbp), %r9
+ movq 56(%rbp), %r10
+ # A[3] x A[2]
+ mulxq 24(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[4] x A[2]
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 40(%rbp)
+ movq %r9, 48(%rbp)
+ movq 64(%rbp), %r8
+ movq 72(%rbp), %r9
+ # A[5] x A[2]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[6] x A[2]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 56(%rbp)
+ movq %r8, 64(%rbp)
+ movq 80(%rbp), %r10
+ movq 88(%rbp), %r8
+ # A[7] x A[2]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[8] x A[2]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 72(%rbp)
+ movq %r10, 80(%rbp)
+ # No load %r13 - %r9
+ # No load %r14 - %r10
+ # A[9] x A[2]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r13
+ # A[10] x A[2]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ movq %r8, 88(%rbp)
+ # No store %r13
+ # No load %r15 - %r8
+ # No load %rbx - %r9
+ # A[11] x A[2]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[12] x A[2]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r10
+ movq 8(%rdi), %r8
+ # A[13] x A[2]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r10
+ # A[14] x A[2]
+ mulxq 112(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # No store %rbx
+ movq %r10, (%rdi)
+ movq 16(%rdi), %r9
+ movq %r11, %r10
+ # A[14] x A[3]
+ movq 112(%rsi), %rdx
+ mulxq 24(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] x A[4]
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r11, %r8
+ # A[14] x A[5]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 24(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 32(%rdi)
+ # Diagonal 4
+ movq 56(%rbp), %r8
+ movq 64(%rbp), %r9
+ movq 72(%rbp), %r10
+ # A[4] x A[3]
+ movq 24(%rsi), %rdx
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[5] x A[3]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 56(%rbp)
+ movq %r9, 64(%rbp)
+ movq 80(%rbp), %r8
+ movq 88(%rbp), %r9
+ # A[6] x A[3]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[7] x A[3]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 72(%rbp)
+ movq %r8, 80(%rbp)
+ # No load %r13 - %r10
+ # No load %r14 - %r8
+ # A[8] x A[3]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r13
+ # A[9] x A[3]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ movq %r9, 88(%rbp)
+ # No store %r13
+ # No load %r15 - %r9
+ # No load %rbx - %r10
+ # A[10] x A[3]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[11] x A[3]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
+ # A[12] x A[3]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r8
+ # A[13] x A[3]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # No store %rbx
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
+ # A[13] x A[4]
+ movq 104(%rsi), %rdx
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[13] x A[5]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq %r11, %r10
+ # A[13] x A[6]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[13] x A[7]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 24(%rdi)
+ movq %r9, 32(%rdi)
+ movq %r11, %r8
+ # A[13] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 40(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 48(%rdi)
+ # Diagonal 5
+ movq 72(%rbp), %r8
+ movq 80(%rbp), %r9
+ movq 88(%rbp), %r10
+ # A[5] x A[4]
+ movq 32(%rsi), %rdx
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[6] x A[4]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 72(%rbp)
+ movq %r9, 80(%rbp)
+ # No load %r13 - %r8
+ # No load %r14 - %r9
+ # A[7] x A[4]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r13
+ # A[8] x A[4]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ movq %r10, 88(%rbp)
+ # No store %r13
+ # No load %r15 - %r10
+ # No load %rbx - %r8
+ # A[9] x A[4]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[10] x A[4]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[11] x A[4]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r9
+ # A[12] x A[4]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # No store %rbx
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ # A[12] x A[5]
+ movq 96(%rsi), %rdx
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[12] x A[6]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r10
+ movq 40(%rdi), %r8
+ # A[12] x A[7]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[12] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 24(%rdi)
+ movq %r10, 32(%rdi)
+ movq 48(%rdi), %r9
+ movq %r11, %r10
+ # A[12] x A[9]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[12] x A[10]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq %r11, %r8
+ # A[12] x A[11]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 56(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 64(%rdi)
+ # Diagonal 6
+ movq 88(%rbp), %r8
+ # No load %r13 - %r9
+ # No load %r14 - %r10
+ # A[6] x A[5]
+ movq 40(%rsi), %rdx
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r13
+ # A[7] x A[5]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ movq %r8, 88(%rbp)
+ # No store %r13
+ # No load %r15 - %r8
+ # No load %rbx - %r9
+ # A[8] x A[5]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[9] x A[5]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r10
+ movq 8(%rdi), %r8
+ # A[10] x A[5]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r10
+ # A[11] x A[5]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # No store %rbx
+ movq %r10, (%rdi)
+ movq 16(%rdi), %r9
+ movq 24(%rdi), %r10
+ # A[11] x A[6]
+ movq 88(%rsi), %rdx
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[11] x A[7]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ # A[11] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[11] x A[9]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 24(%rdi)
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r10
+ movq 56(%rdi), %r8
+ # A[11] x A[10]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[13] x A[9]
+ movq 104(%rsi), %rdx
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 40(%rdi)
+ movq %r10, 48(%rdi)
+ movq 64(%rdi), %r9
+ movq %r11, %r10
+ # A[13] x A[10]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[13] x A[11]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 56(%rdi)
+ movq %r9, 64(%rdi)
+ movq %r11, %r8
+ # A[13] x A[12]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 72(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 80(%rdi)
+ # Diagonal 7
+ # No load %r14 - %r8
+ # No load %r15 - %r9
+ # No load %rbx - %r10
+ # A[7] x A[6]
+ movq 48(%rsi), %rdx
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # A[8] x A[6]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # No store %r14
+ # No store %r15
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
+ # A[9] x A[6]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r8
+ # A[10] x A[6]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # No store %rbx
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r10
+ movq 24(%rdi), %r8
+ # A[10] x A[7]
+ movq 80(%rsi), %rdx
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[10] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 8(%rdi)
+ movq %r10, 16(%rdi)
+ movq 32(%rdi), %r9
+ movq 40(%rdi), %r10
+ # A[10] x A[9]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] x A[6]
+ movq 112(%rsi), %rdx
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 24(%rdi)
+ movq %r9, 32(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
+ # A[14] x A[7]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[14] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r10
+ movq 72(%rdi), %r8
+ # A[14] x A[9]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[14] x A[10]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 56(%rdi)
+ movq %r10, 64(%rdi)
+ movq 80(%rdi), %r9
+ movq %r11, %r10
+ # A[14] x A[11]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[14] x A[12]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r11, %r8
+ # A[14] x A[13]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 88(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 96(%rdi)
+ # Diagonal 8
+ # No load %rbx - %r8
+ movq (%rdi), %r9
+ movq 8(%rdi), %r10
+ # A[8] x A[7]
+ movq 56(%rsi), %rdx
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %rbx
+ adoxq %rcx, %r9
+ # A[9] x A[7]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # No store %rbx
+ movq %r9, (%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ # A[9] x A[8]
+ movq 64(%rsi), %rdx
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[15] x A[3]
+ movq 120(%rsi), %rdx
+ mulxq 24(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r10
+ movq 40(%rdi), %r8
+ # A[15] x A[4]
+ mulxq 32(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[15] x A[5]
+ mulxq 40(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 24(%rdi)
+ movq %r10, 32(%rdi)
+ movq 48(%rdi), %r9
+ movq 56(%rdi), %r10
+ # A[15] x A[6]
+ mulxq 48(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[15] x A[7]
+ mulxq 56(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
+ # A[15] x A[8]
+ mulxq 64(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ # A[15] x A[9]
+ mulxq 72(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ movq %r10, 56(%rdi)
+ movq %r8, 64(%rdi)
+ movq 80(%rdi), %r10
+ movq 88(%rdi), %r8
+ # A[15] x A[10]
+ mulxq 80(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ # A[15] x A[11]
+ mulxq 88(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r9, 72(%rdi)
+ movq %r10, 80(%rdi)
+ movq 96(%rdi), %r9
+ movq %r11, %r10
+ # A[15] x A[12]
+ mulxq 96(%rsi), %rax, %rcx
+ adcxq %rax, %r8
+ adoxq %rcx, %r9
+ # A[15] x A[13]
+ mulxq 104(%rsi), %rax, %rcx
+ adcxq %rax, %r9
+ adoxq %rcx, %r10
+ movq %r8, 88(%rdi)
+ movq %r9, 96(%rdi)
+ movq %r11, %r8
+ # A[15] x A[14]
+ mulxq 112(%rsi), %rax, %rcx
+ adcxq %rax, %r10
+ adoxq %rcx, %r8
+ movq %r10, 104(%rdi)
+ # Carry
+ adcxq %r12, %r8
+ movq %r11, %r12
+ adcxq %r11, %r12
+ adoxq %r11, %r12
+ movq %r8, 112(%rdi)
+ movq %r12, 120(%rdi)
+ # Double and Add in A[i] x A[i]
+ movq 8(%rbp), %r9
+ # A[0] x A[0]
+ movq (%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ movq %rax, (%rbp)
+ adoxq %r9, %r9
+ adcxq %rcx, %r9
+ movq %r9, 8(%rbp)
+ movq 16(%rbp), %r8
+ movq 24(%rbp), %r9
+ # A[1] x A[1]
+ movq 8(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 16(%rbp)
+ movq %r9, 24(%rbp)
+ movq 32(%rbp), %r8
+ movq 40(%rbp), %r9
+ # A[2] x A[2]
+ movq 16(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 32(%rbp)
+ movq %r9, 40(%rbp)
+ movq 48(%rbp), %r8
+ movq 56(%rbp), %r9
+ # A[3] x A[3]
+ movq 24(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 48(%rbp)
+ movq %r9, 56(%rbp)
+ movq 64(%rbp), %r8
+ movq 72(%rbp), %r9
+ # A[4] x A[4]
+ movq 32(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 64(%rbp)
+ movq %r9, 72(%rbp)
+ movq 80(%rbp), %r8
+ movq 88(%rbp), %r9
+ # A[5] x A[5]
+ movq 40(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 80(%rbp)
+ movq %r9, 88(%rbp)
+ # A[6] x A[6]
+ movq 48(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r13, %r13
+ adoxq %r14, %r14
+ adcxq %rax, %r13
+ adcxq %rcx, %r14
+ # A[7] x A[7]
+ movq 56(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r15, %r15
+ adoxq %rbx, %rbx
+ adcxq %rax, %r15
+ adcxq %rcx, %rbx
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
+ # A[8] x A[8]
+ movq 64(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ # A[9] x A[9]
+ movq 72(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdi), %r8
+ movq 40(%rdi), %r9
+ # A[10] x A[10]
+ movq 80(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
+ # A[11] x A[11]
+ movq 88(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
+ # A[12] x A[12]
+ movq 96(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 64(%rdi)
+ movq %r9, 72(%rdi)
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
+ # A[13] x A[13]
+ movq 104(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rdi), %r8
+ movq 104(%rdi), %r9
+ # A[14] x A[14]
+ movq 112(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 96(%rdi)
+ movq %r9, 104(%rdi)
+ movq 112(%rdi), %r8
+ movq 120(%rdi), %r9
+ # A[15] x A[15]
+ movq 120(%rsi), %rdx
+ mulxq %rdx, %rax, %rcx
+ adoxq %r8, %r8
+ adoxq %r9, %r9
+ adcxq %rax, %r8
+ adcxq %rcx, %r9
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ movq %r13, -32(%rdi)
+ movq %r14, -24(%rdi)
+ movq %r15, -16(%rdi)
+ movq %rbx, -8(%rdi)
+ subq $0x80, %rdi
+ cmpq %rdi, %rsi
+ jne L_end_1024_sqr_avx2_16
+ vmovdqu (%rbp), %xmm0
+ vmovups %xmm0, (%rdi)
+ vmovdqu 16(%rbp), %xmm0
+ vmovups %xmm0, 16(%rdi)
+ vmovdqu 32(%rbp), %xmm0
+ vmovups %xmm0, 32(%rdi)
+ vmovdqu 48(%rbp), %xmm0
+ vmovups %xmm0, 48(%rdi)
+ vmovdqu 64(%rbp), %xmm0
+ vmovups %xmm0, 64(%rdi)
+ vmovdqu 80(%rbp), %xmm0
+ vmovups %xmm0, 80(%rdi)
+L_end_1024_sqr_avx2_16:
+ addq $0x80, %rsp
+ popq %rbx
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_sqr_avx2_16,.-sp_1024_sqr_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+/* Add b to a into r. (r = a + b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_add_16
+.type sp_1024_add_16,@function
+.align 16
+sp_1024_add_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_add_16
+.p2align 4
+_sp_1024_add_16:
+#endif /* __APPLE__ */
+ # Add
+ movq (%rsi), %rcx
+ xorq %rax, %rax
+ addq (%rdx), %rcx
+ movq 8(%rsi), %r8
+ movq %rcx, (%rdi)
+ adcq 8(%rdx), %r8
+ movq 16(%rsi), %rcx
+ movq %r8, 8(%rdi)
+ adcq 16(%rdx), %rcx
+ movq 24(%rsi), %r8
+ movq %rcx, 16(%rdi)
+ adcq 24(%rdx), %r8
+ movq 32(%rsi), %rcx
+ movq %r8, 24(%rdi)
+ adcq 32(%rdx), %rcx
+ movq 40(%rsi), %r8
+ movq %rcx, 32(%rdi)
+ adcq 40(%rdx), %r8
+ movq 48(%rsi), %rcx
+ movq %r8, 40(%rdi)
+ adcq 48(%rdx), %rcx
+ movq 56(%rsi), %r8
+ movq %rcx, 48(%rdi)
+ adcq 56(%rdx), %r8
+ movq 64(%rsi), %rcx
+ movq %r8, 56(%rdi)
+ adcq 64(%rdx), %rcx
+ movq 72(%rsi), %r8
+ movq %rcx, 64(%rdi)
+ adcq 72(%rdx), %r8
+ movq 80(%rsi), %rcx
+ movq %r8, 72(%rdi)
+ adcq 80(%rdx), %rcx
+ movq 88(%rsi), %r8
+ movq %rcx, 80(%rdi)
+ adcq 88(%rdx), %r8
+ movq 96(%rsi), %rcx
+ movq %r8, 88(%rdi)
+ adcq 96(%rdx), %rcx
+ movq 104(%rsi), %r8
+ movq %rcx, 96(%rdi)
+ adcq 104(%rdx), %r8
+ movq 112(%rsi), %rcx
+ movq %r8, 104(%rdi)
+ adcq 112(%rdx), %rcx
+ movq 120(%rsi), %r8
+ movq %rcx, 112(%rdi)
+ adcq 120(%rdx), %r8
+ movq %r8, 120(%rdi)
+ adcq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_add_16,.-sp_1024_add_16
+#endif /* __APPLE__ */
+/* Sub b from a into a. (a -= b)
+ *
+ * a A single precision integer and result.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_sub_in_place_16
+.type sp_1024_sub_in_place_16,@function
+.align 16
+sp_1024_sub_in_place_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_sub_in_place_16
+.p2align 4
+_sp_1024_sub_in_place_16:
+#endif /* __APPLE__ */
+ movq (%rdi), %rdx
+ xorq %rax, %rax
+ subq (%rsi), %rdx
+ movq 8(%rdi), %rcx
+ movq %rdx, (%rdi)
+ sbbq 8(%rsi), %rcx
+ movq 16(%rdi), %rdx
+ movq %rcx, 8(%rdi)
+ sbbq 16(%rsi), %rdx
+ movq 24(%rdi), %rcx
+ movq %rdx, 16(%rdi)
+ sbbq 24(%rsi), %rcx
+ movq 32(%rdi), %rdx
+ movq %rcx, 24(%rdi)
+ sbbq 32(%rsi), %rdx
+ movq 40(%rdi), %rcx
+ movq %rdx, 32(%rdi)
+ sbbq 40(%rsi), %rcx
+ movq 48(%rdi), %rdx
+ movq %rcx, 40(%rdi)
+ sbbq 48(%rsi), %rdx
+ movq 56(%rdi), %rcx
+ movq %rdx, 48(%rdi)
+ sbbq 56(%rsi), %rcx
+ movq 64(%rdi), %rdx
+ movq %rcx, 56(%rdi)
+ sbbq 64(%rsi), %rdx
+ movq 72(%rdi), %rcx
+ movq %rdx, 64(%rdi)
+ sbbq 72(%rsi), %rcx
+ movq 80(%rdi), %rdx
+ movq %rcx, 72(%rdi)
+ sbbq 80(%rsi), %rdx
+ movq 88(%rdi), %rcx
+ movq %rdx, 80(%rdi)
+ sbbq 88(%rsi), %rcx
+ movq 96(%rdi), %rdx
+ movq %rcx, 88(%rdi)
+ sbbq 96(%rsi), %rdx
+ movq 104(%rdi), %rcx
+ movq %rdx, 96(%rdi)
+ sbbq 104(%rsi), %rcx
+ movq 112(%rdi), %rdx
+ movq %rcx, 104(%rdi)
+ sbbq 112(%rsi), %rdx
+ movq 120(%rdi), %rcx
+ movq %rdx, 112(%rdi)
+ sbbq 120(%rsi), %rcx
+ movq %rcx, 120(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_sub_in_place_16,.-sp_1024_sub_in_place_16
+#endif /* __APPLE__ */
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_cond_sub_16
+.type sp_1024_cond_sub_16,@function
+.align 16
+sp_1024_cond_sub_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_cond_sub_16
+.p2align 4
+_sp_1024_cond_sub_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq $0x00, %rax
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, (%rsp)
+ movq %r9, 8(%rsp)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 16(%rsp)
+ movq %r9, 24(%rsp)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 32(%rsp)
+ movq %r9, 40(%rsp)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 48(%rsp)
+ movq %r9, 56(%rsp)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 64(%rsp)
+ movq %r9, 72(%rsp)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 80(%rsp)
+ movq %r9, 88(%rsp)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 96(%rsp)
+ movq %r9, 104(%rsp)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ andq %rcx, %r8
+ andq %rcx, %r9
+ movq %r8, 112(%rsp)
+ movq %r9, 120(%rsp)
+ movq (%rsi), %r8
+ movq (%rsp), %rdx
+ subq %rdx, %r8
+ movq 8(%rsi), %r9
+ movq 8(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, (%rdi)
+ movq 16(%rsi), %r8
+ movq 16(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 8(%rdi)
+ movq 24(%rsi), %r9
+ movq 24(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 16(%rdi)
+ movq 32(%rsi), %r8
+ movq 32(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 24(%rdi)
+ movq 40(%rsi), %r9
+ movq 40(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 32(%rdi)
+ movq 48(%rsi), %r8
+ movq 48(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 40(%rdi)
+ movq 56(%rsi), %r9
+ movq 56(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 48(%rdi)
+ movq 64(%rsi), %r8
+ movq 64(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 56(%rdi)
+ movq 72(%rsi), %r9
+ movq 72(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 64(%rdi)
+ movq 80(%rsi), %r8
+ movq 80(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 72(%rdi)
+ movq 88(%rsi), %r9
+ movq 88(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 80(%rdi)
+ movq 96(%rsi), %r8
+ movq 96(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 88(%rdi)
+ movq 104(%rsi), %r9
+ movq 104(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 96(%rdi)
+ movq 112(%rsi), %r8
+ movq 112(%rsp), %rdx
+ sbbq %rdx, %r8
+ movq %r9, 104(%rdi)
+ movq 120(%rsi), %r9
+ movq 120(%rsp), %rdx
+ sbbq %rdx, %r9
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %rax
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_cond_sub_16,.-sp_1024_cond_sub_16
+#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
+/* Conditionally subtract b from a using the mask m.
+ * m is -1 to subtract and 0 when not copying.
+ *
+ * r A single precision number representing condition subtract result.
+ * a A single precision number to subtract from.
+ * b A single precision number to subtract.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_cond_sub_avx2_16
+.type sp_1024_cond_sub_avx2_16,@function
+.align 16
+sp_1024_cond_sub_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_cond_sub_avx2_16
+.p2align 4
+_sp_1024_cond_sub_avx2_16:
+#endif /* __APPLE__ */
+ movq $0x00, %rax
+ movq (%rdx), %r10
+ movq (%rsi), %r8
+ pextq %rcx, %r10, %r10
+ subq %r10, %r8
+ movq 8(%rdx), %r10
+ movq 8(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, (%rdi)
+ sbbq %r10, %r9
+ movq 16(%rdx), %r8
+ movq 16(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 8(%rdi)
+ sbbq %r8, %r10
+ movq 24(%rdx), %r9
+ movq 24(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 16(%rdi)
+ sbbq %r9, %r8
+ movq 32(%rdx), %r10
+ movq 32(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, 24(%rdi)
+ sbbq %r10, %r9
+ movq 40(%rdx), %r8
+ movq 40(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 32(%rdi)
+ sbbq %r8, %r10
+ movq 48(%rdx), %r9
+ movq 48(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 40(%rdi)
+ sbbq %r9, %r8
+ movq 56(%rdx), %r10
+ movq 56(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, 48(%rdi)
+ sbbq %r10, %r9
+ movq 64(%rdx), %r8
+ movq 64(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 56(%rdi)
+ sbbq %r8, %r10
+ movq 72(%rdx), %r9
+ movq 72(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 64(%rdi)
+ sbbq %r9, %r8
+ movq 80(%rdx), %r10
+ movq 80(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, 72(%rdi)
+ sbbq %r10, %r9
+ movq 88(%rdx), %r8
+ movq 88(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 80(%rdi)
+ sbbq %r8, %r10
+ movq 96(%rdx), %r9
+ movq 96(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 88(%rdi)
+ sbbq %r9, %r8
+ movq 104(%rdx), %r10
+ movq 104(%rsi), %r9
+ pextq %rcx, %r10, %r10
+ movq %r8, 96(%rdi)
+ sbbq %r10, %r9
+ movq 112(%rdx), %r8
+ movq 112(%rsi), %r10
+ pextq %rcx, %r8, %r8
+ movq %r9, 104(%rdi)
+ sbbq %r8, %r10
+ movq 120(%rdx), %r9
+ movq 120(%rsi), %r8
+ pextq %rcx, %r9, %r9
+ movq %r10, 112(%rdi)
+ sbbq %r9, %r8
+ movq %r8, 120(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_cond_sub_avx2_16,.-sp_1024_cond_sub_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+/* Mul a by digit b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision digit.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mul_d_16
+.type sp_1024_mul_d_16,@function
+.align 16
+sp_1024_mul_d_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mul_d_16
+.p2align 4
+_sp_1024_mul_d_16:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ # A[0] * B
+ movq %rcx, %rax
+ xorq %r10, %r10
+ mulq (%rsi)
+ movq %rax, %r8
+ movq %rdx, %r9
+ movq %r8, (%rdi)
+ # A[1] * B
+ movq %rcx, %rax
+ xorq %r8, %r8
+ mulq 8(%rsi)
+ addq %rax, %r9
+ movq %r9, 8(%rdi)
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[2] * B
+ movq %rcx, %rax
+ xorq %r9, %r9
+ mulq 16(%rsi)
+ addq %rax, %r10
+ movq %r10, 16(%rdi)
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[3] * B
+ movq %rcx, %rax
+ xorq %r10, %r10
+ mulq 24(%rsi)
+ addq %rax, %r8
+ movq %r8, 24(%rdi)
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[4] * B
+ movq %rcx, %rax
+ xorq %r8, %r8
+ mulq 32(%rsi)
+ addq %rax, %r9
+ movq %r9, 32(%rdi)
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[5] * B
+ movq %rcx, %rax
+ xorq %r9, %r9
+ mulq 40(%rsi)
+ addq %rax, %r10
+ movq %r10, 40(%rdi)
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[6] * B
+ movq %rcx, %rax
+ xorq %r10, %r10
+ mulq 48(%rsi)
+ addq %rax, %r8
+ movq %r8, 48(%rdi)
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[7] * B
+ movq %rcx, %rax
+ xorq %r8, %r8
+ mulq 56(%rsi)
+ addq %rax, %r9
+ movq %r9, 56(%rdi)
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[8] * B
+ movq %rcx, %rax
+ xorq %r9, %r9
+ mulq 64(%rsi)
+ addq %rax, %r10
+ movq %r10, 64(%rdi)
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[9] * B
+ movq %rcx, %rax
+ xorq %r10, %r10
+ mulq 72(%rsi)
+ addq %rax, %r8
+ movq %r8, 72(%rdi)
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[10] * B
+ movq %rcx, %rax
+ xorq %r8, %r8
+ mulq 80(%rsi)
+ addq %rax, %r9
+ movq %r9, 80(%rdi)
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[11] * B
+ movq %rcx, %rax
+ xorq %r9, %r9
+ mulq 88(%rsi)
+ addq %rax, %r10
+ movq %r10, 88(%rdi)
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[12] * B
+ movq %rcx, %rax
+ xorq %r10, %r10
+ mulq 96(%rsi)
+ addq %rax, %r8
+ movq %r8, 96(%rdi)
+ adcq %rdx, %r9
+ adcq $0x00, %r10
+ # A[13] * B
+ movq %rcx, %rax
+ xorq %r8, %r8
+ mulq 104(%rsi)
+ addq %rax, %r9
+ movq %r9, 104(%rdi)
+ adcq %rdx, %r10
+ adcq $0x00, %r8
+ # A[14] * B
+ movq %rcx, %rax
+ xorq %r9, %r9
+ mulq 112(%rsi)
+ addq %rax, %r10
+ movq %r10, 112(%rdi)
+ adcq %rdx, %r8
+ adcq $0x00, %r9
+ # A[15] * B
+ movq %rcx, %rax
+ mulq 120(%rsi)
+ addq %rax, %r8
+ adcq %rdx, %r9
+ movq %r8, 120(%rdi)
+ movq %r9, 128(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mul_d_16,.-sp_1024_mul_d_16
+#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
+/* Mul a by digit b into r. (r = a * b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision digit.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mul_d_avx2_16
+.type sp_1024_mul_d_avx2_16,@function
+.align 16
+sp_1024_mul_d_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mul_d_avx2_16
+.p2align 4
+_sp_1024_mul_d_avx2_16:
+#endif /* __APPLE__ */
+ movq %rdx, %rax
+ # A[0] * B
+ movq %rax, %rdx
+ xorq %r11, %r11
+ mulxq (%rsi), %r9, %r10
+ movq %r9, (%rdi)
+ # A[1] * B
+ mulxq 8(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 8(%rdi)
+ # A[2] * B
+ mulxq 16(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 16(%rdi)
+ # A[3] * B
+ mulxq 24(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 24(%rdi)
+ # A[4] * B
+ mulxq 32(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 32(%rdi)
+ # A[5] * B
+ mulxq 40(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 40(%rdi)
+ # A[6] * B
+ mulxq 48(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 48(%rdi)
+ # A[7] * B
+ mulxq 56(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 56(%rdi)
+ # A[8] * B
+ mulxq 64(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 64(%rdi)
+ # A[9] * B
+ mulxq 72(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 72(%rdi)
+ # A[10] * B
+ mulxq 80(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 80(%rdi)
+ # A[11] * B
+ mulxq 88(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 88(%rdi)
+ # A[12] * B
+ mulxq 96(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 96(%rdi)
+ # A[13] * B
+ mulxq 104(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ movq %r10, 104(%rdi)
+ # A[14] * B
+ mulxq 112(%rsi), %rcx, %r8
+ movq %r11, %r10
+ adcxq %rcx, %r9
+ adoxq %r8, %r10
+ movq %r9, 112(%rdi)
+ # A[15] * B
+ mulxq 120(%rsi), %rcx, %r8
+ movq %r11, %r9
+ adcxq %rcx, %r10
+ adoxq %r8, %r9
+ adcxq %r11, %r9
+ movq %r10, 120(%rdi)
+ movq %r9, 128(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mul_d_avx2_16,.-sp_1024_mul_d_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef _WIN64
+/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+ *
+ * d1 The high order half of the number to divide.
+ * d0 The low order half of the number to divide.
+ * div The dividend.
+ * returns the result of the division.
+ */
+#ifndef __APPLE__
+.text
+.globl div_1024_word_asm_16
+.type div_1024_word_asm_16,@function
+.align 16
+div_1024_word_asm_16:
+#else
+.section __TEXT,__text
+.globl _div_1024_word_asm_16
+.p2align 4
+_div_1024_word_asm_16:
+#endif /* __APPLE__ */
+ movq %rdx, %rcx
+ movq %rsi, %rax
+ movq %rdi, %rdx
+ divq %rcx
+ repz retq
+#ifndef __APPLE__
+.size div_1024_word_asm_16,.-div_1024_word_asm_16
+#endif /* __APPLE__ */
+#endif /* _WIN64 */
+/* Compare a with b in constant time.
+ *
+ * a A single precision integer.
+ * b A single precision integer.
+ * return -ve, 0 or +ve if a is less than, equal to or greater than b
+ * respectively.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_cmp_16
+.type sp_1024_cmp_16,@function
+.align 16
+sp_1024_cmp_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_cmp_16
+.p2align 4
+_sp_1024_cmp_16:
+#endif /* __APPLE__ */
+ xorq %rcx, %rcx
+ movq $-1, %rdx
+ movq $-1, %rax
+ movq $0x01, %r8
+ movq 120(%rdi), %r9
+ movq 120(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 112(%rdi), %r9
+ movq 112(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 104(%rdi), %r9
+ movq 104(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 96(%rdi), %r9
+ movq 96(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 88(%rdi), %r9
+ movq 88(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 80(%rdi), %r9
+ movq 80(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 72(%rdi), %r9
+ movq 72(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 64(%rdi), %r9
+ movq 64(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 56(%rdi), %r9
+ movq 56(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 48(%rdi), %r9
+ movq 48(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 40(%rdi), %r9
+ movq 40(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 32(%rdi), %r9
+ movq 32(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 24(%rdi), %r9
+ movq 24(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 16(%rdi), %r9
+ movq 16(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq 8(%rdi), %r9
+ movq 8(%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ movq (%rdi), %r9
+ movq (%rsi), %r10
+ andq %rdx, %r9
+ andq %rdx, %r10
+ subq %r10, %r9
+ cmova %r8, %rax
+ cmovc %rdx, %rax
+ cmovnz %rcx, %rdx
+ xorq %rdx, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_cmp_16,.-sp_1024_cmp_16
+#endif /* __APPLE__ */
+/* Conditionally copy a into r using the mask m.
+ * m is -1 to copy and 0 when not.
+ *
+ * r A single precision number to copy over.
+ * a A single precision number to copy.
+ * m Mask value to apply.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_cond_copy_16
+.type sp_1024_cond_copy_16,@function
+.align 16
+sp_1024_cond_copy_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_cond_copy_16
+.p2align 4
+_sp_1024_cond_copy_16:
+#endif /* __APPLE__ */
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ xorq (%rsi), %rax
+ xorq 8(%rsi), %rcx
+ xorq 16(%rsi), %r8
+ xorq 24(%rsi), %r9
+ andq %rdx, %rax
+ andq %rdx, %rcx
+ andq %rdx, %r8
+ andq %rdx, %r9
+ xorq %rax, (%rdi)
+ xorq %rcx, 8(%rdi)
+ xorq %r8, 16(%rdi)
+ xorq %r9, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
+ xorq 32(%rsi), %rax
+ xorq 40(%rsi), %rcx
+ xorq 48(%rsi), %r8
+ xorq 56(%rsi), %r9
+ andq %rdx, %rax
+ andq %rdx, %rcx
+ andq %rdx, %r8
+ andq %rdx, %r9
+ xorq %rax, 32(%rdi)
+ xorq %rcx, 40(%rdi)
+ xorq %r8, 48(%rdi)
+ xorq %r9, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
+ xorq 64(%rsi), %rax
+ xorq 72(%rsi), %rcx
+ xorq 80(%rsi), %r8
+ xorq 88(%rsi), %r9
+ andq %rdx, %rax
+ andq %rdx, %rcx
+ andq %rdx, %r8
+ andq %rdx, %r9
+ xorq %rax, 64(%rdi)
+ xorq %rcx, 72(%rdi)
+ xorq %r8, 80(%rdi)
+ xorq %r9, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ movq 112(%rdi), %r8
+ movq 120(%rdi), %r9
+ xorq 96(%rsi), %rax
+ xorq 104(%rsi), %rcx
+ xorq 112(%rsi), %r8
+ xorq 120(%rsi), %r9
+ andq %rdx, %rax
+ andq %rdx, %rcx
+ andq %rdx, %r8
+ andq %rdx, %r9
+ xorq %rax, 96(%rdi)
+ xorq %rcx, 104(%rdi)
+ xorq %r8, 112(%rdi)
+ xorq %r9, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_cond_copy_16,.-sp_1024_cond_copy_16
+#endif /* __APPLE__ */
+/* Reduce the number back to 1024 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_reduce_16
+.type sp_1024_mont_reduce_16,@function
+.align 16
+sp_1024_mont_reduce_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_reduce_16
+.p2align 4
+_sp_1024_mont_reduce_16:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rdx, %rcx
+ xorq %r15, %r15
+ # i = 16
+ movq $16, %r8
+ movq (%rdi), %r13
+ movq 8(%rdi), %r14
+L_1024_mont_loop_16:
+ # mu = a[i] * mp
+ movq %r13, %r11
+ imulq %rcx, %r11
+ # a[i+0] += m[0] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq (%rsi)
+ addq %rax, %r13
+ adcq %rdx, %r10
+ # a[i+1] += m[1] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 8(%rsi)
+ movq %r14, %r13
+ addq %rax, %r13
+ adcq %rdx, %r9
+ addq %r10, %r13
+ adcq $0x00, %r9
+ # a[i+2] += m[2] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 16(%rsi)
+ movq 16(%rdi), %r14
+ addq %rax, %r14
+ adcq %rdx, %r10
+ addq %r9, %r14
+ adcq $0x00, %r10
+ # a[i+3] += m[3] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 24(%rsi)
+ movq 24(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 24(%rdi)
+ adcq $0x00, %r9
+ # a[i+4] += m[4] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 32(%rsi)
+ movq 32(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 32(%rdi)
+ adcq $0x00, %r10
+ # a[i+5] += m[5] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 40(%rsi)
+ movq 40(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 40(%rdi)
+ adcq $0x00, %r9
+ # a[i+6] += m[6] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 48(%rsi)
+ movq 48(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 48(%rdi)
+ adcq $0x00, %r10
+ # a[i+7] += m[7] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 56(%rsi)
+ movq 56(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 56(%rdi)
+ adcq $0x00, %r9
+ # a[i+8] += m[8] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 64(%rsi)
+ movq 64(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 64(%rdi)
+ adcq $0x00, %r10
+ # a[i+9] += m[9] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 72(%rsi)
+ movq 72(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 72(%rdi)
+ adcq $0x00, %r9
+ # a[i+10] += m[10] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 80(%rsi)
+ movq 80(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 80(%rdi)
+ adcq $0x00, %r10
+ # a[i+11] += m[11] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 88(%rsi)
+ movq 88(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 88(%rdi)
+ adcq $0x00, %r9
+ # a[i+12] += m[12] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 96(%rsi)
+ movq 96(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 96(%rdi)
+ adcq $0x00, %r10
+ # a[i+13] += m[13] * mu
+ movq %r11, %rax
+ xorq %r9, %r9
+ mulq 104(%rsi)
+ movq 104(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r9
+ addq %r10, %r12
+ movq %r12, 104(%rdi)
+ adcq $0x00, %r9
+ # a[i+14] += m[14] * mu
+ movq %r11, %rax
+ xorq %r10, %r10
+ mulq 112(%rsi)
+ movq 112(%rdi), %r12
+ addq %rax, %r12
+ adcq %rdx, %r10
+ addq %r9, %r12
+ movq %r12, 112(%rdi)
+ adcq $0x00, %r10
+ # a[i+15] += m[15] * mu
+ movq %r11, %rax
+ mulq 120(%rsi)
+ movq 120(%rdi), %r12
+ addq %rax, %r10
+ adcq %r15, %rdx
+ movq $0x00, %r15
+ adcq $0x00, %r15
+ addq %r10, %r12
+ movq %r12, 120(%rdi)
+ adcq %rdx, 128(%rdi)
+ adcq $0x00, %r15
+ # i -= 1
+ addq $8, %rdi
+ decq %r8
+ jnz L_1024_mont_loop_16
+ movq 120(%rdi), %r12
+ movq %r13, (%rdi)
+ subq 120(%rsi), %r12
+ movq %r14, 8(%rdi)
+ sbbq %r12, %r12
+ negq %r15
+ notq %r12
+ orq %r12, %r15
+#ifdef _WIN64
+ movq %rsi, %rdx
+ movq %r15, %rcx
+#else
+ movq %r15, %rcx
+ movq %rsi, %rdx
+#endif /* _WIN64 */
+ movq %rdi, %rsi
+ movq %rdi, %rdi
+ subq $0x80, %rdi
+#ifndef __APPLE__
+ callq sp_1024_cond_sub_16@plt
+#else
+ callq _sp_1024_cond_sub_16
+#endif /* __APPLE__ */
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_reduce_16,.-sp_1024_mont_reduce_16
+#endif /* __APPLE__ */
+/* Add two Montgomery form numbers (r = a + b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_add_16
+.type sp_1024_mont_add_16,@function
+.align 16
+sp_1024_mont_add_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_add_16
+.p2align 4
+_sp_1024_mont_add_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq (%rsi), %rax
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ addq (%rdx), %rax
+ movq $0x00, %r11
+ adcq 8(%rdx), %r8
+ adcq 16(%rdx), %r9
+ adcq 24(%rdx), %r10
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %r8
+ movq 48(%rsi), %r9
+ movq 56(%rsi), %r10
+ adcq 32(%rdx), %rax
+ adcq 40(%rdx), %r8
+ adcq 48(%rdx), %r9
+ adcq 56(%rdx), %r10
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq %r10, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %r8
+ movq 80(%rsi), %r9
+ movq 88(%rsi), %r10
+ adcq 64(%rdx), %rax
+ adcq 72(%rdx), %r8
+ adcq 80(%rdx), %r9
+ adcq 88(%rdx), %r10
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %r8
+ movq 112(%rsi), %r9
+ movq 120(%rsi), %r10
+ adcq 96(%rdx), %rax
+ adcq 104(%rdx), %r8
+ adcq 112(%rdx), %r9
+ adcq 120(%rdx), %r10
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq %r9, 112(%rdi)
+ movq %r10, 120(%rdi)
+ sbbq $0x00, %r11
+ subq 120(%rcx), %r10
+ sbbq %r10, %r10
+ notq %r10
+ orq %r10, %r11
+ movq (%rcx), %r9
+ movq 8(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, (%rsp)
+ movq %r10, 8(%rsp)
+ movq 16(%rcx), %r9
+ movq 24(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 16(%rsp)
+ movq %r10, 24(%rsp)
+ movq 32(%rcx), %r9
+ movq 40(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 32(%rsp)
+ movq %r10, 40(%rsp)
+ movq 48(%rcx), %r9
+ movq 56(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 48(%rsp)
+ movq %r10, 56(%rsp)
+ movq 64(%rcx), %r9
+ movq 72(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 64(%rsp)
+ movq %r10, 72(%rsp)
+ movq 80(%rcx), %r9
+ movq 88(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 80(%rsp)
+ movq %r10, 88(%rsp)
+ movq 96(%rcx), %r9
+ movq 104(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 96(%rsp)
+ movq %r10, 104(%rsp)
+ movq 112(%rcx), %r9
+ movq 120(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 112(%rsp)
+ movq %r10, 120(%rsp)
+ movq (%rdi), %rax
+ movq 8(%rdi), %r8
+ subq (%rsp), %rax
+ sbbq 8(%rsp), %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %r8
+ sbbq 16(%rsp), %rax
+ sbbq 24(%rsp), %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %r8
+ sbbq 32(%rsp), %rax
+ sbbq 40(%rsp), %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %r8
+ sbbq 48(%rsp), %rax
+ sbbq 56(%rsp), %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %r8
+ sbbq 64(%rsp), %rax
+ sbbq 72(%rsp), %r8
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %r8
+ sbbq 80(%rsp), %rax
+ sbbq 88(%rsp), %r8
+ movq %rax, 80(%rdi)
+ movq %r8, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %r8
+ sbbq 96(%rsp), %rax
+ sbbq 104(%rsp), %r8
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %r8
+ sbbq 112(%rsp), %rax
+ sbbq 120(%rsp), %r8
+ movq %rax, 112(%rdi)
+ movq %r8, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_add_16,.-sp_1024_mont_add_16
+#endif /* __APPLE__ */
+/* Double a Montgomery form number (r = a + a % m).
+ *
+ * r Result of addition.
+ * a Number to souble in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_dbl_16
+.type sp_1024_mont_dbl_16,@function
+.align 16
+sp_1024_mont_dbl_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_dbl_16
+.p2align 4
+_sp_1024_mont_dbl_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq (%rsi), %rax
+ movq 8(%rsi), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %rcx
+ movq 48(%rsi), %r8
+ movq 56(%rsi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %rcx
+ movq 80(%rsi), %r8
+ movq 88(%rsi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %rcx
+ movq 112(%rsi), %r8
+ movq 120(%rsi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, (%rsp)
+ movq %r9, 8(%rsp)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 16(%rsp)
+ movq %r9, 24(%rsp)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 32(%rsp)
+ movq %r9, 40(%rsp)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 48(%rsp)
+ movq %r9, 56(%rsp)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 64(%rsp)
+ movq %r9, 72(%rsp)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 80(%rsp)
+ movq %r9, 88(%rsp)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 96(%rsp)
+ movq %r9, 104(%rsp)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 112(%rsp)
+ movq %r9, 120(%rsp)
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ subq (%rsp), %rax
+ sbbq 8(%rsp), %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ sbbq 16(%rsp), %rax
+ sbbq 24(%rsp), %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ sbbq 32(%rsp), %rax
+ sbbq 40(%rsp), %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ sbbq 48(%rsp), %rax
+ sbbq 56(%rsp), %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ sbbq 64(%rsp), %rax
+ sbbq 72(%rsp), %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ sbbq 80(%rsp), %rax
+ sbbq 88(%rsp), %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ sbbq 96(%rsp), %rax
+ sbbq 104(%rsp), %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ sbbq 112(%rsp), %rax
+ sbbq 120(%rsp), %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_dbl_16,.-sp_1024_mont_dbl_16
+#endif /* __APPLE__ */
+/* Triple a Montgomery form number (r = a + a + a % m).
+ *
+ * r Result of addition.
+ * a Number to souble in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_tpl_16
+.type sp_1024_mont_tpl_16,@function
+.align 16
+sp_1024_mont_tpl_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_tpl_16
+.p2align 4
+_sp_1024_mont_tpl_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq (%rsi), %rax
+ movq 8(%rsi), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %rcx
+ movq 48(%rsi), %r8
+ movq 56(%rsi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %rcx
+ movq 80(%rsi), %r8
+ movq 88(%rsi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %rcx
+ movq 112(%rsi), %r8
+ movq 120(%rsi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, (%rsp)
+ movq %r9, 8(%rsp)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 16(%rsp)
+ movq %r9, 24(%rsp)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 32(%rsp)
+ movq %r9, 40(%rsp)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 48(%rsp)
+ movq %r9, 56(%rsp)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 64(%rsp)
+ movq %r9, 72(%rsp)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 80(%rsp)
+ movq %r9, 88(%rsp)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 96(%rsp)
+ movq %r9, 104(%rsp)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 112(%rsp)
+ movq %r9, 120(%rsp)
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ subq (%rsp), %rax
+ sbbq 8(%rsp), %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ sbbq 16(%rsp), %rax
+ sbbq 24(%rsp), %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ sbbq 32(%rsp), %rax
+ sbbq 40(%rsp), %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ sbbq 48(%rsp), %rax
+ sbbq 56(%rsp), %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ sbbq 64(%rsp), %rax
+ sbbq 72(%rsp), %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ sbbq 80(%rsp), %rax
+ sbbq 88(%rsp), %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ sbbq 96(%rsp), %rax
+ sbbq 104(%rsp), %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ sbbq 112(%rsp), %rax
+ sbbq 120(%rsp), %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ movq 112(%rdi), %r8
+ movq 120(%rdi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, (%rsp)
+ movq %r9, 8(%rsp)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 16(%rsp)
+ movq %r9, 24(%rsp)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 32(%rsp)
+ movq %r9, 40(%rsp)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 48(%rsp)
+ movq %r9, 56(%rsp)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 64(%rsp)
+ movq %r9, 72(%rsp)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 80(%rsp)
+ movq %r9, 88(%rsp)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 96(%rsp)
+ movq %r9, 104(%rsp)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ andq %r10, %r8
+ andq %r10, %r9
+ movq %r8, 112(%rsp)
+ movq %r9, 120(%rsp)
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ subq (%rsp), %rax
+ sbbq 8(%rsp), %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ sbbq 16(%rsp), %rax
+ sbbq 24(%rsp), %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ sbbq 32(%rsp), %rax
+ sbbq 40(%rsp), %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ sbbq 48(%rsp), %rax
+ sbbq 56(%rsp), %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ sbbq 64(%rsp), %rax
+ sbbq 72(%rsp), %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ sbbq 80(%rsp), %rax
+ sbbq 88(%rsp), %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ sbbq 96(%rsp), %rax
+ sbbq 104(%rsp), %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ sbbq 112(%rsp), %rax
+ sbbq 120(%rsp), %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_tpl_16,.-sp_1024_mont_tpl_16
+#endif /* __APPLE__ */
+/* Subtract two Montgomery form numbers (r = a - b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_sub_16
+.type sp_1024_mont_sub_16,@function
+.align 16
+sp_1024_mont_sub_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_sub_16
+.p2align 4
+_sp_1024_mont_sub_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq (%rsi), %rax
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ subq (%rdx), %rax
+ movq $0x00, %r11
+ sbbq 8(%rdx), %r8
+ sbbq 16(%rdx), %r9
+ sbbq 24(%rdx), %r10
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %r8
+ movq 48(%rsi), %r9
+ movq 56(%rsi), %r10
+ sbbq 32(%rdx), %rax
+ sbbq 40(%rdx), %r8
+ sbbq 48(%rdx), %r9
+ sbbq 56(%rdx), %r10
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq %r10, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %r8
+ movq 80(%rsi), %r9
+ movq 88(%rsi), %r10
+ sbbq 64(%rdx), %rax
+ sbbq 72(%rdx), %r8
+ sbbq 80(%rdx), %r9
+ sbbq 88(%rdx), %r10
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %r8
+ movq 112(%rsi), %r9
+ movq 120(%rsi), %r10
+ sbbq 96(%rdx), %rax
+ sbbq 104(%rdx), %r8
+ sbbq 112(%rdx), %r9
+ sbbq 120(%rdx), %r10
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq %r9, 112(%rdi)
+ movq %r10, 120(%rdi)
+ sbbq $0x00, %r11
+ movq (%rcx), %r9
+ movq 8(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, (%rsp)
+ movq %r10, 8(%rsp)
+ movq 16(%rcx), %r9
+ movq 24(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 16(%rsp)
+ movq %r10, 24(%rsp)
+ movq 32(%rcx), %r9
+ movq 40(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 32(%rsp)
+ movq %r10, 40(%rsp)
+ movq 48(%rcx), %r9
+ movq 56(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 48(%rsp)
+ movq %r10, 56(%rsp)
+ movq 64(%rcx), %r9
+ movq 72(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 64(%rsp)
+ movq %r10, 72(%rsp)
+ movq 80(%rcx), %r9
+ movq 88(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 80(%rsp)
+ movq %r10, 88(%rsp)
+ movq 96(%rcx), %r9
+ movq 104(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 96(%rsp)
+ movq %r10, 104(%rsp)
+ movq 112(%rcx), %r9
+ movq 120(%rcx), %r10
+ andq %r11, %r9
+ andq %r11, %r10
+ movq %r9, 112(%rsp)
+ movq %r10, 120(%rsp)
+ movq (%rdi), %rax
+ movq 8(%rdi), %r8
+ addq (%rsp), %rax
+ adcq 8(%rsp), %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %r8
+ adcq 16(%rsp), %rax
+ adcq 24(%rsp), %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %r8
+ adcq 32(%rsp), %rax
+ adcq 40(%rsp), %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %r8
+ adcq 48(%rsp), %rax
+ adcq 56(%rsp), %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %r8
+ adcq 64(%rsp), %rax
+ adcq 72(%rsp), %r8
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %r8
+ adcq 80(%rsp), %rax
+ adcq 88(%rsp), %r8
+ movq %rax, 80(%rdi)
+ movq %r8, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %r8
+ adcq 96(%rsp), %rax
+ adcq 104(%rsp), %r8
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %r8
+ adcq 112(%rsp), %rax
+ adcq 120(%rsp), %r8
+ movq %rax, 112(%rdi)
+ movq %r8, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_sub_16,.-sp_1024_mont_sub_16
+#endif /* __APPLE__ */
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_div2_16
+.type sp_1024_div2_16,@function
+.align 16
+sp_1024_div2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_div2_16
+.p2align 4
+_sp_1024_div2_16:
+#endif /* __APPLE__ */
+ subq $0x80, %rsp
+ movq (%rsi), %r11
+ xorq %r10, %r10
+ movq %r11, %rax
+ andq $0x01, %r11
+ negq %r11
+ movq (%rdx), %r8
+ andq %r11, %r8
+ movq %r8, (%rsp)
+ movq 8(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 8(%rsp)
+ movq 16(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 16(%rsp)
+ movq 24(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 24(%rsp)
+ movq 32(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 32(%rsp)
+ movq 40(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 40(%rsp)
+ movq 48(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 48(%rsp)
+ movq 56(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 56(%rsp)
+ movq 64(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 64(%rsp)
+ movq 72(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 72(%rsp)
+ movq 80(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 80(%rsp)
+ movq 88(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 88(%rsp)
+ movq 96(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 96(%rsp)
+ movq 104(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 104(%rsp)
+ movq 112(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 112(%rsp)
+ movq 120(%rdx), %r8
+ andq %r11, %r8
+ movq %r8, 120(%rsp)
+ addq %rax, (%rsp)
+ movq 8(%rsi), %rax
+ adcq %rax, 8(%rsp)
+ movq 16(%rsi), %rax
+ adcq %rax, 16(%rsp)
+ movq 24(%rsi), %rax
+ adcq %rax, 24(%rsp)
+ movq 32(%rsi), %rax
+ adcq %rax, 32(%rsp)
+ movq 40(%rsi), %rax
+ adcq %rax, 40(%rsp)
+ movq 48(%rsi), %rax
+ adcq %rax, 48(%rsp)
+ movq 56(%rsi), %rax
+ adcq %rax, 56(%rsp)
+ movq 64(%rsi), %rax
+ adcq %rax, 64(%rsp)
+ movq 72(%rsi), %rax
+ adcq %rax, 72(%rsp)
+ movq 80(%rsi), %rax
+ adcq %rax, 80(%rsp)
+ movq 88(%rsi), %rax
+ adcq %rax, 88(%rsp)
+ movq 96(%rsi), %rax
+ adcq %rax, 96(%rsp)
+ movq 104(%rsi), %rax
+ adcq %rax, 104(%rsp)
+ movq 112(%rsi), %rax
+ adcq %rax, 112(%rsp)
+ movq 120(%rsi), %rax
+ adcq %rax, 120(%rsp)
+ adcq $0x00, %r10
+ movq (%rsp), %rax
+ movq 8(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, (%rdi)
+ movq 16(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 8(%rdi)
+ movq 24(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 16(%rdi)
+ movq 32(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 24(%rdi)
+ movq 40(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 32(%rdi)
+ movq 48(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 40(%rdi)
+ movq 56(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 48(%rdi)
+ movq 64(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 56(%rdi)
+ movq 72(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 64(%rdi)
+ movq 80(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 72(%rdi)
+ movq 88(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 80(%rdi)
+ movq 96(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 88(%rdi)
+ movq 104(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 96(%rdi)
+ movq 112(%rsp), %rax
+ shrdq $0x01, %rax, %rcx
+ movq %rcx, 104(%rdi)
+ movq 120(%rsp), %rcx
+ shrdq $0x01, %rcx, %rax
+ movq %rax, 112(%rdi)
+ shrdq $0x01, %r10, %rcx
+ movq %rcx, 120(%rdi)
+ addq $0x80, %rsp
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_div2_16,.-sp_1024_div2_16
+#endif /* __APPLE__ */
+/* Sub b from a into r. (r = a - b)
+ *
+ * r A single precision integer.
+ * a A single precision integer.
+ * b A single precision integer.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_sub_16
+.type sp_1024_sub_16,@function
+.align 16
+sp_1024_sub_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_sub_16
+.p2align 4
+_sp_1024_sub_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %rcx
+ xorq %rax, %rax
+ subq (%rdx), %rcx
+ movq 8(%rsi), %r8
+ movq %rcx, (%rdi)
+ sbbq 8(%rdx), %r8
+ movq 16(%rsi), %rcx
+ movq %r8, 8(%rdi)
+ sbbq 16(%rdx), %rcx
+ movq 24(%rsi), %r8
+ movq %rcx, 16(%rdi)
+ sbbq 24(%rdx), %r8
+ movq 32(%rsi), %rcx
+ movq %r8, 24(%rdi)
+ sbbq 32(%rdx), %rcx
+ movq 40(%rsi), %r8
+ movq %rcx, 32(%rdi)
+ sbbq 40(%rdx), %r8
+ movq 48(%rsi), %rcx
+ movq %r8, 40(%rdi)
+ sbbq 48(%rdx), %rcx
+ movq 56(%rsi), %r8
+ movq %rcx, 48(%rdi)
+ sbbq 56(%rdx), %r8
+ movq 64(%rsi), %rcx
+ movq %r8, 56(%rdi)
+ sbbq 64(%rdx), %rcx
+ movq 72(%rsi), %r8
+ movq %rcx, 64(%rdi)
+ sbbq 72(%rdx), %r8
+ movq 80(%rsi), %rcx
+ movq %r8, 72(%rdi)
+ sbbq 80(%rdx), %rcx
+ movq 88(%rsi), %r8
+ movq %rcx, 80(%rdi)
+ sbbq 88(%rdx), %r8
+ movq 96(%rsi), %rcx
+ movq %r8, 88(%rdi)
+ sbbq 96(%rdx), %rcx
+ movq 104(%rsi), %r8
+ movq %rcx, 96(%rdi)
+ sbbq 104(%rdx), %r8
+ movq 112(%rsi), %rcx
+ movq %r8, 104(%rdi)
+ sbbq 112(%rdx), %rcx
+ movq 120(%rsi), %r8
+ movq %rcx, 112(%rdi)
+ sbbq 120(%rdx), %r8
+ movq %r8, 120(%rdi)
+ sbbq $0x00, %rax
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_sub_16,.-sp_1024_sub_16
+#endif /* __APPLE__ */
+#ifdef HAVE_INTEL_AVX2
+/* Reduce the number back to 1024 bits using Montgomery reduction.
+ *
+ * a A single precision number to reduce in place.
+ * m The single precision number representing the modulus.
+ * mp The digit representing the negative inverse of m mod 2^n.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_reduce_avx2_16
+.type sp_1024_mont_reduce_avx2_16,@function
+.align 16
+sp_1024_mont_reduce_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_reduce_avx2_16
+.p2align 4
+_sp_1024_mont_reduce_avx2_16:
+#endif /* __APPLE__ */
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq %rbx
+ pushq %rbp
+ movq %rdx, %r8
+ xorq %rbp, %rbp
+ # i = 16
+ movq $16, %r9
+ movq (%rdi), %r13
+ movq 8(%rdi), %r14
+ movq 16(%rdi), %r15
+ movq 24(%rdi), %rbx
+ addq $0x40, %rdi
+ xorq %rbp, %rbp
+L_1024_mont_loop_avx2_16:
+ # mu = a[i] * mp
+ movq %r13, %rdx
+ movq %r13, %r10
+ imulq %r8, %rdx
+ xorq %r12, %r12
+ # a[i+0] += m[0] * mu
+ mulxq (%rsi), %rax, %rcx
+ movq %r14, %r13
+ adcxq %rax, %r10
+ adoxq %rcx, %r13
+ # a[i+1] += m[1] * mu
+ mulxq 8(%rsi), %rax, %rcx
+ movq %r15, %r14
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ # a[i+2] += m[2] * mu
+ mulxq 16(%rsi), %rax, %rcx
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # a[i+3] += m[3] * mu
+ mulxq 24(%rsi), %rax, %rcx
+ movq -32(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # a[i+4] += m[4] * mu
+ mulxq 32(%rsi), %rax, %rcx
+ movq -24(%rdi), %r11
+ adcxq %rax, %rbx
+ adoxq %rcx, %r11
+ # a[i+5] += m[5] * mu
+ mulxq 40(%rsi), %rax, %rcx
+ movq -16(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, -24(%rdi)
+ # a[i+6] += m[6] * mu
+ mulxq 48(%rsi), %rax, %rcx
+ movq -8(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, -16(%rdi)
+ # a[i+7] += m[7] * mu
+ mulxq 56(%rsi), %rax, %rcx
+ movq (%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, -8(%rdi)
+ # a[i+8] += m[8] * mu
+ mulxq 64(%rsi), %rax, %rcx
+ movq 8(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, (%rdi)
+ # a[i+9] += m[9] * mu
+ mulxq 72(%rsi), %rax, %rcx
+ movq 16(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 8(%rdi)
+ # a[i+10] += m[10] * mu
+ mulxq 80(%rsi), %rax, %rcx
+ movq 24(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 16(%rdi)
+ # a[i+11] += m[11] * mu
+ mulxq 88(%rsi), %rax, %rcx
+ movq 32(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 24(%rdi)
+ # a[i+12] += m[12] * mu
+ mulxq 96(%rsi), %rax, %rcx
+ movq 40(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 32(%rdi)
+ # a[i+13] += m[13] * mu
+ mulxq 104(%rsi), %rax, %rcx
+ movq 48(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 40(%rdi)
+ # a[i+14] += m[14] * mu
+ mulxq 112(%rsi), %rax, %rcx
+ movq 56(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 48(%rdi)
+ # a[i+15] += m[15] * mu
+ mulxq 120(%rsi), %rax, %rcx
+ movq 64(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 56(%rdi)
+ adcxq %rbp, %r10
+ movq %r12, %rbp
+ movq %r10, 64(%rdi)
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
+ # mu = a[i] * mp
+ movq %r13, %rdx
+ movq %r13, %r10
+ imulq %r8, %rdx
+ xorq %r12, %r12
+ # a[i+0] += m[0] * mu
+ mulxq (%rsi), %rax, %rcx
+ movq %r14, %r13
+ adcxq %rax, %r10
+ adoxq %rcx, %r13
+ # a[i+1] += m[1] * mu
+ mulxq 8(%rsi), %rax, %rcx
+ movq %r15, %r14
+ adcxq %rax, %r13
+ adoxq %rcx, %r14
+ # a[i+2] += m[2] * mu
+ mulxq 16(%rsi), %rax, %rcx
+ movq %rbx, %r15
+ adcxq %rax, %r14
+ adoxq %rcx, %r15
+ # a[i+3] += m[3] * mu
+ mulxq 24(%rsi), %rax, %rcx
+ movq -24(%rdi), %rbx
+ adcxq %rax, %r15
+ adoxq %rcx, %rbx
+ # a[i+4] += m[4] * mu
+ mulxq 32(%rsi), %rax, %rcx
+ movq -16(%rdi), %r11
+ adcxq %rax, %rbx
+ adoxq %rcx, %r11
+ # a[i+5] += m[5] * mu
+ mulxq 40(%rsi), %rax, %rcx
+ movq -8(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, -16(%rdi)
+ # a[i+6] += m[6] * mu
+ mulxq 48(%rsi), %rax, %rcx
+ movq (%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, -8(%rdi)
+ # a[i+7] += m[7] * mu
+ mulxq 56(%rsi), %rax, %rcx
+ movq 8(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, (%rdi)
+ # a[i+8] += m[8] * mu
+ mulxq 64(%rsi), %rax, %rcx
+ movq 16(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 8(%rdi)
+ # a[i+9] += m[9] * mu
+ mulxq 72(%rsi), %rax, %rcx
+ movq 24(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 16(%rdi)
+ # a[i+10] += m[10] * mu
+ mulxq 80(%rsi), %rax, %rcx
+ movq 32(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 24(%rdi)
+ # a[i+11] += m[11] * mu
+ mulxq 88(%rsi), %rax, %rcx
+ movq 40(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 32(%rdi)
+ # a[i+12] += m[12] * mu
+ mulxq 96(%rsi), %rax, %rcx
+ movq 48(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 40(%rdi)
+ # a[i+13] += m[13] * mu
+ mulxq 104(%rsi), %rax, %rcx
+ movq 56(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 48(%rdi)
+ # a[i+14] += m[14] * mu
+ mulxq 112(%rsi), %rax, %rcx
+ movq 64(%rdi), %r11
+ adcxq %rax, %r10
+ adoxq %rcx, %r11
+ movq %r10, 56(%rdi)
+ # a[i+15] += m[15] * mu
+ mulxq 120(%rsi), %rax, %rcx
+ movq 72(%rdi), %r10
+ adcxq %rax, %r11
+ adoxq %rcx, %r10
+ movq %r11, 64(%rdi)
+ adcxq %rbp, %r10
+ movq %r12, %rbp
+ movq %r10, 72(%rdi)
+ adoxq %r12, %rbp
+ adcxq %r12, %rbp
+ # a += 2
+ addq $16, %rdi
+ # i -= 2
+ subq $2, %r9
+ jnz L_1024_mont_loop_avx2_16
+ subq $0x40, %rdi
+ subq 120(%rsi), %r10
+ movq %rdi, %r8
+ sbbq %r10, %r10
+ negq %rbp
+ notq %r10
+ orq %r10, %rbp
+ subq $0x80, %rdi
+ movq (%rsi), %rcx
+ movq %r13, %rdx
+ pextq %rbp, %rcx, %rcx
+ subq %rcx, %rdx
+ movq 8(%rsi), %rcx
+ movq %r14, %rax
+ pextq %rbp, %rcx, %rcx
+ movq %rdx, (%rdi)
+ sbbq %rcx, %rax
+ movq 16(%rsi), %rdx
+ movq %r15, %rcx
+ pextq %rbp, %rdx, %rdx
+ movq %rax, 8(%rdi)
+ sbbq %rdx, %rcx
+ movq 24(%rsi), %rax
+ movq %rbx, %rdx
+ pextq %rbp, %rax, %rax
+ movq %rcx, 16(%rdi)
+ sbbq %rax, %rdx
+ movq 32(%rsi), %rcx
+ movq 32(%r8), %rax
+ pextq %rbp, %rcx, %rcx
+ movq %rdx, 24(%rdi)
+ sbbq %rcx, %rax
+ movq 40(%rsi), %rdx
+ movq 40(%r8), %rcx
+ pextq %rbp, %rdx, %rdx
+ movq %rax, 32(%rdi)
+ sbbq %rdx, %rcx
+ movq 48(%rsi), %rax
+ movq 48(%r8), %rdx
+ pextq %rbp, %rax, %rax
+ movq %rcx, 40(%rdi)
+ sbbq %rax, %rdx
+ movq 56(%rsi), %rcx
+ movq 56(%r8), %rax
+ pextq %rbp, %rcx, %rcx
+ movq %rdx, 48(%rdi)
+ sbbq %rcx, %rax
+ movq 64(%rsi), %rdx
+ movq 64(%r8), %rcx
+ pextq %rbp, %rdx, %rdx
+ movq %rax, 56(%rdi)
+ sbbq %rdx, %rcx
+ movq 72(%rsi), %rax
+ movq 72(%r8), %rdx
+ pextq %rbp, %rax, %rax
+ movq %rcx, 64(%rdi)
+ sbbq %rax, %rdx
+ movq 80(%rsi), %rcx
+ movq 80(%r8), %rax
+ pextq %rbp, %rcx, %rcx
+ movq %rdx, 72(%rdi)
+ sbbq %rcx, %rax
+ movq 88(%rsi), %rdx
+ movq 88(%r8), %rcx
+ pextq %rbp, %rdx, %rdx
+ movq %rax, 80(%rdi)
+ sbbq %rdx, %rcx
+ movq 96(%rsi), %rax
+ movq 96(%r8), %rdx
+ pextq %rbp, %rax, %rax
+ movq %rcx, 88(%rdi)
+ sbbq %rax, %rdx
+ movq 104(%rsi), %rcx
+ movq 104(%r8), %rax
+ pextq %rbp, %rcx, %rcx
+ movq %rdx, 96(%rdi)
+ sbbq %rcx, %rax
+ movq 112(%rsi), %rdx
+ movq 112(%r8), %rcx
+ pextq %rbp, %rdx, %rdx
+ movq %rax, 104(%rdi)
+ sbbq %rdx, %rcx
+ movq 120(%rsi), %rax
+ movq 120(%r8), %rdx
+ pextq %rbp, %rax, %rax
+ movq %rcx, 112(%rdi)
+ sbbq %rax, %rdx
+ movq %rdx, 120(%rdi)
+ popq %rbp
+ popq %rbx
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_reduce_avx2_16,.-sp_1024_mont_reduce_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Add two Montgomery form numbers (r = a + b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_add_avx2_16
+.type sp_1024_mont_add_avx2_16,@function
+.align 16
+sp_1024_mont_add_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_add_avx2_16
+.p2align 4
+_sp_1024_mont_add_avx2_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %rax
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ addq (%rdx), %rax
+ movq $0x00, %r11
+ adcq 8(%rdx), %r8
+ adcq 16(%rdx), %r9
+ adcq 24(%rdx), %r10
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %r8
+ movq 48(%rsi), %r9
+ movq 56(%rsi), %r10
+ adcq 32(%rdx), %rax
+ adcq 40(%rdx), %r8
+ adcq 48(%rdx), %r9
+ adcq 56(%rdx), %r10
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq %r10, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %r8
+ movq 80(%rsi), %r9
+ movq 88(%rsi), %r10
+ adcq 64(%rdx), %rax
+ adcq 72(%rdx), %r8
+ adcq 80(%rdx), %r9
+ adcq 88(%rdx), %r10
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %r8
+ movq 112(%rsi), %r9
+ movq 120(%rsi), %r10
+ adcq 96(%rdx), %rax
+ adcq 104(%rdx), %r8
+ adcq 112(%rdx), %r9
+ adcq 120(%rdx), %r10
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq %r9, 112(%rdi)
+ movq %r10, 120(%rdi)
+ sbbq $0x00, %r11
+ subq 120(%rcx), %r10
+ sbbq %r10, %r10
+ notq %r10
+ orq %r10, %r11
+ movq (%rcx), %r9
+ movq 8(%rcx), %r10
+ movq (%rdi), %rax
+ movq 8(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ subq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq 16(%rcx), %r9
+ movq 24(%rcx), %r10
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movq 32(%rcx), %r9
+ movq 40(%rcx), %r10
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq 48(%rcx), %r9
+ movq 56(%rcx), %r10
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ movq 64(%rcx), %r9
+ movq 72(%rcx), %r10
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq 80(%rcx), %r9
+ movq 88(%rcx), %r10
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 80(%rdi)
+ movq %r8, 88(%rdi)
+ movq 96(%rcx), %r9
+ movq 104(%rcx), %r10
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq 112(%rcx), %r9
+ movq 120(%rcx), %r10
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ sbbq %r9, %rax
+ sbbq %r10, %r8
+ movq %rax, 112(%rdi)
+ movq %r8, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_add_avx2_16,.-sp_1024_mont_add_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Double a Montgomery form number (r = a + a % m).
+ *
+ * r Result of addition.
+ * a Number to souble in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_dbl_avx2_16
+.type sp_1024_mont_dbl_avx2_16,@function
+.align 16
+sp_1024_mont_dbl_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_dbl_avx2_16
+.p2align 4
+_sp_1024_mont_dbl_avx2_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %rax
+ movq 8(%rsi), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %rcx
+ movq 48(%rsi), %r8
+ movq 56(%rsi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %rcx
+ movq 80(%rsi), %r8
+ movq 88(%rsi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %rcx
+ movq 112(%rsi), %r8
+ movq 120(%rsi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ subq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_dbl_avx2_16,.-sp_1024_mont_dbl_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Triple a Montgomery form number (r = a + a + a % m).
+ *
+ * r Result of addition.
+ * a Number to souble in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_tpl_avx2_16
+.type sp_1024_mont_tpl_avx2_16,@function
+.align 16
+sp_1024_mont_tpl_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_tpl_avx2_16
+.p2align 4
+_sp_1024_mont_tpl_avx2_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %rax
+ movq 8(%rsi), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %rcx
+ movq 48(%rsi), %r8
+ movq 56(%rsi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %rcx
+ movq 80(%rsi), %r8
+ movq 88(%rsi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %rcx
+ movq 112(%rsi), %r8
+ movq 120(%rsi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ subq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ movq 16(%rdi), %r8
+ movq 24(%rdi), %r9
+ addq (%rsi), %rax
+ movq $0x00, %r10
+ adcq 8(%rsi), %rcx
+ adcq 16(%rsi), %r8
+ adcq 24(%rsi), %r9
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ movq 48(%rdi), %r8
+ movq 56(%rdi), %r9
+ adcq 32(%rsi), %rax
+ adcq 40(%rsi), %rcx
+ adcq 48(%rsi), %r8
+ adcq 56(%rsi), %r9
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ movq 80(%rdi), %r8
+ movq 88(%rdi), %r9
+ adcq 64(%rsi), %rax
+ adcq 72(%rsi), %rcx
+ adcq 80(%rsi), %r8
+ adcq 88(%rsi), %r9
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ movq 112(%rdi), %r8
+ movq 120(%rdi), %r9
+ adcq 96(%rsi), %rax
+ adcq 104(%rsi), %rcx
+ adcq 112(%rsi), %r8
+ adcq 120(%rsi), %r9
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ sbbq $0x00, %r10
+ subq 120(%rdx), %r9
+ sbbq %r9, %r9
+ notq %r9
+ orq %r9, %r10
+ movq (%rdx), %r8
+ movq 8(%rdx), %r9
+ movq (%rdi), %rax
+ movq 8(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ subq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, (%rdi)
+ movq %rcx, 8(%rdi)
+ movq 16(%rdx), %r8
+ movq 24(%rdx), %r9
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 16(%rdi)
+ movq %rcx, 24(%rdi)
+ movq 32(%rdx), %r8
+ movq 40(%rdx), %r9
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 32(%rdi)
+ movq %rcx, 40(%rdi)
+ movq 48(%rdx), %r8
+ movq 56(%rdx), %r9
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 48(%rdi)
+ movq %rcx, 56(%rdi)
+ movq 64(%rdx), %r8
+ movq 72(%rdx), %r9
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 64(%rdi)
+ movq %rcx, 72(%rdi)
+ movq 80(%rdx), %r8
+ movq 88(%rdx), %r9
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 80(%rdi)
+ movq %rcx, 88(%rdi)
+ movq 96(%rdx), %r8
+ movq 104(%rdx), %r9
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 96(%rdi)
+ movq %rcx, 104(%rdi)
+ movq 112(%rdx), %r8
+ movq 120(%rdx), %r9
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %rcx
+ pextq %r10, %r8, %r8
+ pextq %r10, %r9, %r9
+ sbbq %r8, %rax
+ sbbq %r9, %rcx
+ movq %rax, 112(%rdi)
+ movq %rcx, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_tpl_avx2_16,.-sp_1024_mont_tpl_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Subtract two Montgomery form numbers (r = a - b % m).
+ *
+ * r Result of addition.
+ * a First number to add in Montogmery form.
+ * b Second number to add in Montogmery form.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_mont_sub_avx2_16
+.type sp_1024_mont_sub_avx2_16,@function
+.align 16
+sp_1024_mont_sub_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_mont_sub_avx2_16
+.p2align 4
+_sp_1024_mont_sub_avx2_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %rax
+ movq 8(%rsi), %r8
+ movq 16(%rsi), %r9
+ movq 24(%rsi), %r10
+ subq (%rdx), %rax
+ movq $0x00, %r11
+ sbbq 8(%rdx), %r8
+ sbbq 16(%rdx), %r9
+ sbbq 24(%rdx), %r10
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq %r9, 16(%rdi)
+ movq %r10, 24(%rdi)
+ movq 32(%rsi), %rax
+ movq 40(%rsi), %r8
+ movq 48(%rsi), %r9
+ movq 56(%rsi), %r10
+ sbbq 32(%rdx), %rax
+ sbbq 40(%rdx), %r8
+ sbbq 48(%rdx), %r9
+ sbbq 56(%rdx), %r10
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq %r9, 48(%rdi)
+ movq %r10, 56(%rdi)
+ movq 64(%rsi), %rax
+ movq 72(%rsi), %r8
+ movq 80(%rsi), %r9
+ movq 88(%rsi), %r10
+ sbbq 64(%rdx), %rax
+ sbbq 72(%rdx), %r8
+ sbbq 80(%rdx), %r9
+ sbbq 88(%rdx), %r10
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq %r9, 80(%rdi)
+ movq %r10, 88(%rdi)
+ movq 96(%rsi), %rax
+ movq 104(%rsi), %r8
+ movq 112(%rsi), %r9
+ movq 120(%rsi), %r10
+ sbbq 96(%rdx), %rax
+ sbbq 104(%rdx), %r8
+ sbbq 112(%rdx), %r9
+ sbbq 120(%rdx), %r10
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq %r9, 112(%rdi)
+ movq %r10, 120(%rdi)
+ sbbq $0x00, %r11
+ movq (%rcx), %r9
+ movq 8(%rcx), %r10
+ movq (%rdi), %rax
+ movq 8(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ addq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq 16(%rcx), %r9
+ movq 24(%rcx), %r10
+ movq 16(%rdi), %rax
+ movq 24(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movq 32(%rcx), %r9
+ movq 40(%rcx), %r10
+ movq 32(%rdi), %rax
+ movq 40(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq 48(%rcx), %r9
+ movq 56(%rcx), %r10
+ movq 48(%rdi), %rax
+ movq 56(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ movq 64(%rcx), %r9
+ movq 72(%rcx), %r10
+ movq 64(%rdi), %rax
+ movq 72(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 64(%rdi)
+ movq %r8, 72(%rdi)
+ movq 80(%rcx), %r9
+ movq 88(%rcx), %r10
+ movq 80(%rdi), %rax
+ movq 88(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 80(%rdi)
+ movq %r8, 88(%rdi)
+ movq 96(%rcx), %r9
+ movq 104(%rcx), %r10
+ movq 96(%rdi), %rax
+ movq 104(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 96(%rdi)
+ movq %r8, 104(%rdi)
+ movq 112(%rcx), %r9
+ movq 120(%rcx), %r10
+ movq 112(%rdi), %rax
+ movq 120(%rdi), %r8
+ pextq %r11, %r9, %r9
+ pextq %r11, %r10, %r10
+ adcq %r9, %rax
+ adcq %r10, %r8
+ movq %rax, 112(%rdi)
+ movq %r8, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_mont_sub_avx2_16,.-sp_1024_mont_sub_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+#ifdef HAVE_INTEL_AVX2
+/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+ *
+ * r Result of division by 2.
+ * a Number to divide.
+ * m Modulus (prime).
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_div2_avx2_16
+.type sp_1024_div2_avx2_16,@function
+.align 16
+sp_1024_div2_avx2_16:
+#else
+.section __TEXT,__text
+.globl _sp_1024_div2_avx2_16
+.p2align 4
+_sp_1024_div2_avx2_16:
+#endif /* __APPLE__ */
+ movq (%rsi), %r11
+ xorq %r10, %r10
+ movq %r11, %r8
+ andq $0x01, %r11
+ negq %r11
+ movq (%rdx), %rax
+ movq 8(%rdx), %rcx
+ movq (%rsi), %r8
+ movq 8(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ addq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, (%rdi)
+ movq %r9, 8(%rdi)
+ movq 16(%rdx), %rax
+ movq 24(%rdx), %rcx
+ movq 16(%rsi), %r8
+ movq 24(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 16(%rdi)
+ movq %r9, 24(%rdi)
+ movq 32(%rdx), %rax
+ movq 40(%rdx), %rcx
+ movq 32(%rsi), %r8
+ movq 40(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 32(%rdi)
+ movq %r9, 40(%rdi)
+ movq 48(%rdx), %rax
+ movq 56(%rdx), %rcx
+ movq 48(%rsi), %r8
+ movq 56(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 48(%rdi)
+ movq %r9, 56(%rdi)
+ movq 64(%rdx), %rax
+ movq 72(%rdx), %rcx
+ movq 64(%rsi), %r8
+ movq 72(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 64(%rdi)
+ movq %r9, 72(%rdi)
+ movq 80(%rdx), %rax
+ movq 88(%rdx), %rcx
+ movq 80(%rsi), %r8
+ movq 88(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 80(%rdi)
+ movq %r9, 88(%rdi)
+ movq 96(%rdx), %rax
+ movq 104(%rdx), %rcx
+ movq 96(%rsi), %r8
+ movq 104(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 96(%rdi)
+ movq %r9, 104(%rdi)
+ movq 112(%rdx), %rax
+ movq 120(%rdx), %rcx
+ movq 112(%rsi), %r8
+ movq 120(%rsi), %r9
+ pextq %r11, %rax, %rax
+ pextq %r11, %rcx, %rcx
+ adcq %rax, %r8
+ adcq %rcx, %r9
+ movq %r8, 112(%rdi)
+ movq %r9, 120(%rdi)
+ adcq $0x00, %r10
+ movq (%rdi), %r8
+ movq 8(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, (%rdi)
+ movq 16(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 8(%rdi)
+ movq 24(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 16(%rdi)
+ movq 32(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 24(%rdi)
+ movq 40(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 32(%rdi)
+ movq 48(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 40(%rdi)
+ movq 56(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 48(%rdi)
+ movq 64(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 56(%rdi)
+ movq 72(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 64(%rdi)
+ movq 80(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 72(%rdi)
+ movq 88(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 80(%rdi)
+ movq 96(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 88(%rdi)
+ movq 104(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 96(%rdi)
+ movq 112(%rdi), %r8
+ shrdq $0x01, %r8, %r9
+ movq %r9, 104(%rdi)
+ movq 120(%rdi), %r9
+ shrdq $0x01, %r9, %r8
+ movq %r8, 112(%rdi)
+ shrdq $0x01, %r10, %r9
+ movq %r9, 120(%rdi)
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_div2_avx2_16,.-sp_1024_div2_avx2_16
+#endif /* __APPLE__ */
+#endif /* HAVE_INTEL_AVX2 */
+/* Read big endian unsigned byte array into r.
+ * Uses the bswap instruction.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_from_bin_bswap
+.type sp_1024_from_bin_bswap,@function
+.align 16
+sp_1024_from_bin_bswap:
+#else
+.section __TEXT,__text
+.globl _sp_1024_from_bin_bswap
+.p2align 4
+_sp_1024_from_bin_bswap:
+#endif /* __APPLE__ */
+ movq %rdx, %r9
+ movq %rdi, %r10
+ addq %rcx, %r9
+ addq $0x80, %r10
+ xorq %r11, %r11
+ jmp L_1024_from_bin_bswap_64_end
+L_1024_from_bin_bswap_64_start:
+ subq $0x40, %r9
+ movq 56(%r9), %rax
+ movq 48(%r9), %r8
+ bswapq %rax
+ bswapq %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movq 40(%r9), %rax
+ movq 32(%r9), %r8
+ bswapq %rax
+ bswapq %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movq 24(%r9), %rax
+ movq 16(%r9), %r8
+ bswapq %rax
+ bswapq %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movq 8(%r9), %rax
+ movq (%r9), %r8
+ bswapq %rax
+ bswapq %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ addq $0x40, %rdi
+ subq $0x40, %rcx
+L_1024_from_bin_bswap_64_end:
+ cmpq $63, %rcx
+ jg L_1024_from_bin_bswap_64_start
+ jmp L_1024_from_bin_bswap_8_end
+L_1024_from_bin_bswap_8_start:
+ subq $8, %r9
+ movq (%r9), %rax
+ bswapq %rax
+ movq %rax, (%rdi)
+ addq $8, %rdi
+ subq $8, %rcx
+L_1024_from_bin_bswap_8_end:
+ cmpq $7, %rcx
+ jg L_1024_from_bin_bswap_8_start
+ cmpq %r11, %rcx
+ je L_1024_from_bin_bswap_hi_end
+ movq %r11, %r8
+ movq %r11, %rax
+L_1024_from_bin_bswap_hi_start:
+ movb (%rdx), %al
+ shlq $8, %r8
+ incq %rdx
+ addq %rax, %r8
+ decq %rcx
+ jg L_1024_from_bin_bswap_hi_start
+ movq %r8, (%rdi)
+ addq $8, %rdi
+L_1024_from_bin_bswap_hi_end:
+ cmpq %r10, %rdi
+ je L_1024_from_bin_bswap_zero_end
+L_1024_from_bin_bswap_zero_start:
+ movq %r11, (%rdi)
+ addq $8, %rdi
+ cmpq %r10, %rdi
+ jl L_1024_from_bin_bswap_zero_start
+L_1024_from_bin_bswap_zero_end:
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_from_bin_bswap,.-sp_1024_from_bin_bswap
+#endif /* __APPLE__ */
+#ifndef NO_MOVBE_SUPPORT
+/* Read big endian unsigned byte array into r.
+ * Uses the movbe instruction which is an optional instruction.
+ *
+ * r A single precision integer.
+ * size Maximum number of bytes to convert
+ * a Byte array.
+ * n Number of bytes in array to read.
+ */
+#ifndef __APPLE__
+.text
+.globl sp_1024_from_bin_movbe
+.type sp_1024_from_bin_movbe,@function
+.align 16
+sp_1024_from_bin_movbe:
+#else
+.section __TEXT,__text
+.globl _sp_1024_from_bin_movbe
+.p2align 4
+_sp_1024_from_bin_movbe:
+#endif /* __APPLE__ */
+ movq %rdx, %r9
+ movq %rdi, %r10
+ addq %rcx, %r9
+ addq $0x80, %r10
+ xorq %r11, %r11
+ jmp L_1024_from_bin_movbe_64_end
+L_1024_from_bin_movbe_64_start:
+ subq $0x40, %r9
+ movbeq 56(%r9), %rax
+ movbeq 48(%r9), %r8
+ movq %rax, (%rdi)
+ movq %r8, 8(%rdi)
+ movbeq 40(%r9), %rax
+ movbeq 32(%r9), %r8
+ movq %rax, 16(%rdi)
+ movq %r8, 24(%rdi)
+ movbeq 24(%r9), %rax
+ movbeq 16(%r9), %r8
+ movq %rax, 32(%rdi)
+ movq %r8, 40(%rdi)
+ movbeq 8(%r9), %rax
+ movbeq (%r9), %r8
+ movq %rax, 48(%rdi)
+ movq %r8, 56(%rdi)
+ addq $0x40, %rdi
+ subq $0x40, %rcx
+L_1024_from_bin_movbe_64_end:
+ cmpq $63, %rcx
+ jg L_1024_from_bin_movbe_64_start
+ jmp L_1024_from_bin_movbe_8_end
+L_1024_from_bin_movbe_8_start:
+ subq $8, %r9
+ movbeq (%r9), %rax
+ movq %rax, (%rdi)
+ addq $8, %rdi
+ subq $8, %rcx
+L_1024_from_bin_movbe_8_end:
+ cmpq $7, %rcx
+ jg L_1024_from_bin_movbe_8_start
+ cmpq %r11, %rcx
+ je L_1024_from_bin_movbe_hi_end
+ movq %r11, %r8
+ movq %r11, %rax
+L_1024_from_bin_movbe_hi_start:
+ movb (%rdx), %al
+ shlq $8, %r8
+ incq %rdx
+ addq %rax, %r8
+ decq %rcx
+ jg L_1024_from_bin_movbe_hi_start
+ movq %r8, (%rdi)
+ addq $8, %rdi
+L_1024_from_bin_movbe_hi_end:
+ cmpq %r10, %rdi
+ je L_1024_from_bin_movbe_zero_end
+L_1024_from_bin_movbe_zero_start:
+ movq %r11, (%rdi)
+ addq $8, %rdi
+ cmpq %r10, %rdi
+ jl L_1024_from_bin_movbe_zero_start
+L_1024_from_bin_movbe_zero_end:
+ repz retq
+#ifndef __APPLE__
+.size sp_1024_from_bin_movbe,.-sp_1024_from_bin_movbe
+#endif /* __APPLE__ */
+#endif /* !NO_MOVBE_SUPPORT */
+#endif /* WOLFSSL_SP_1024 */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
diff --git a/wolfcrypt/src/sp_x86_64_asm.asm b/wolfcrypt/src/sp_x86_64_asm.asm
new file mode 100644
index 000000000..7a2aa12cb
--- /dev/null
+++ b/wolfcrypt/src/sp_x86_64_asm.asm
@@ -0,0 +1,52665 @@
+; /* sp_x86_64_asm
+; *
+; * Copyright (C) 2006-2021 wolfSSL Inc.
+; *
+; * This file is part of wolfSSL.
+; *
+; * wolfSSL is free software; you can redistribute it and/or modify
+; * it under the terms of the GNU General Public License as published by
+; * the Free Software Foundation; either version 2 of the License, or
+; * (at your option) any later version.
+; *
+; * wolfSSL is distributed in the hope that it will be useful,
+; * but WITHOUT ANY WARRANTY; without even the implied warranty of
+; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; * GNU General Public License for more details.
+; *
+; * You should have received a copy of the GNU General Public License
+; * along with this program; if not, write to the Free Software
+; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+; */
+IF @Version LT 1200
+; AVX2 instructions not recognized by old versions of MASM
+IFNDEF NO_AVX2_SUPPORT
+NO_AVX2_SUPPORT = 1
+ENDIF
+; MOVBE instruction not recognized by old versions of MASM
+IFNDEF NO_MOVBE_SUPPORT
+NO_MOVBE_SUPPORT = 1
+ENDIF
+ENDIF
+
+IFNDEF HAVE_INTEL_AVX1
+HAVE_INTEL_AVX1 = 1
+ENDIF
+IFNDEF NO_AVX2_SUPPORT
+HAVE_INTEL_AVX2 = 1
+ENDIF
+
+IFNDEF _WIN64
+_WIN64 = 1
+ENDIF
+
+IFNDEF WOLFSSL_SP_NO_2048
+IFNDEF WOLFSSL_SP_NO_2048
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 256
+ xor r13, r13
+ jmp L_2048_from_bin_bswap_64_end
+L_2048_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_2048_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_2048_from_bin_bswap_64_start
+ jmp L_2048_from_bin_bswap_8_end
+L_2048_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_2048_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_2048_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_2048_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_2048_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_2048_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_2048_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_2048_from_bin_bswap_zero_end
+L_2048_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_2048_from_bin_bswap_zero_start
+L_2048_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_2048_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 256
+ xor r13, r13
+ jmp L_2048_from_bin_movbe_64_end
+L_2048_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_2048_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_2048_from_bin_movbe_64_start
+ jmp L_2048_from_bin_movbe_8_end
+L_2048_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_2048_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_2048_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_2048_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_2048_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_2048_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_2048_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_2048_from_bin_movbe_zero_end
+L_2048_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_2048_from_bin_movbe_zero_start
+L_2048_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_2048_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 256
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_to_bin_bswap PROC
+ mov rax, QWORD PTR [rcx+248]
+ mov r8, QWORD PTR [rcx+240]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ mov rax, QWORD PTR [rcx+232]
+ mov r8, QWORD PTR [rcx+224]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ mov rax, QWORD PTR [rcx+216]
+ mov r8, QWORD PTR [rcx+208]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ mov rax, QWORD PTR [rcx+200]
+ mov r8, QWORD PTR [rcx+192]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ mov rax, QWORD PTR [rcx+184]
+ mov r8, QWORD PTR [rcx+176]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ mov rax, QWORD PTR [rcx+168]
+ mov r8, QWORD PTR [rcx+160]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ mov rax, QWORD PTR [rcx+152]
+ mov r8, QWORD PTR [rcx+144]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ mov rax, QWORD PTR [rcx+136]
+ mov r8, QWORD PTR [rcx+128]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ mov rax, QWORD PTR [rcx+120]
+ mov r8, QWORD PTR [rcx+112]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ mov rax, QWORD PTR [rcx+104]
+ mov r8, QWORD PTR [rcx+96]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ mov rax, QWORD PTR [rcx+88]
+ mov r8, QWORD PTR [rcx+80]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ mov rax, QWORD PTR [rcx+72]
+ mov r8, QWORD PTR [rcx+64]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ mov rax, QWORD PTR [rcx+56]
+ mov r8, QWORD PTR [rcx+48]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ mov rax, QWORD PTR [rcx+40]
+ mov r8, QWORD PTR [rcx+32]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ mov rax, QWORD PTR [rcx+24]
+ mov r8, QWORD PTR [rcx+16]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ mov rax, QWORD PTR [rcx+8]
+ mov r8, QWORD PTR [rcx]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ ret
+sp_2048_to_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 256
+; * Uses the movbe instruction which is optional.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_to_bin_movbe PROC
+ movbe rax, QWORD PTR [rcx+248]
+ movbe r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ movbe rax, QWORD PTR [rcx+232]
+ movbe r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ movbe rax, QWORD PTR [rcx+216]
+ movbe r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ movbe rax, QWORD PTR [rcx+200]
+ movbe r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ movbe rax, QWORD PTR [rcx+184]
+ movbe r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ movbe rax, QWORD PTR [rcx+168]
+ movbe r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ movbe rax, QWORD PTR [rcx+152]
+ movbe r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ movbe rax, QWORD PTR [rcx+136]
+ movbe r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ movbe rax, QWORD PTR [rcx+120]
+ movbe r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ movbe rax, QWORD PTR [rcx+104]
+ movbe r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ movbe rax, QWORD PTR [rcx+88]
+ movbe r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ movbe rax, QWORD PTR [rcx+72]
+ movbe r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ movbe rax, QWORD PTR [rcx+56]
+ movbe r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ movbe rax, QWORD PTR [rcx+40]
+ movbe r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ movbe rax, QWORD PTR [rcx+24]
+ movbe r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ movbe rax, QWORD PTR [rcx+8]
+ movbe r8, QWORD PTR [rcx]
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ ret
+sp_2048_to_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_16 PROC
+ push r12
+ mov r9, rdx
+ sub rsp, 128
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ mov QWORD PTR [rsp], rax
+ mov r11, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+8], r11
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+16], r12
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+24], r10
+ ; A[0] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+32], r11
+ ; A[0] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+40], r12
+ ; A[0] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+48], r10
+ ; A[0] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+56], r11
+ ; A[0] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+64], r12
+ ; A[0] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+72], r10
+ ; A[0] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+80], r11
+ ; A[0] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+88], r12
+ ; A[0] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+96], r10
+ ; A[0] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+104], r11
+ ; A[0] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+112], r12
+ ; A[0] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+120], r10
+ ; A[1] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+8]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+128], r11
+ ; A[2] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+16]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+136], r12
+ ; A[3] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+24]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+144], r10
+ ; A[4] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+32]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+152], r11
+ ; A[5] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+40]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+160], r12
+ ; A[6] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+48]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+168], r10
+ ; A[7] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+56]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+176], r11
+ ; A[8] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+64]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+184], r12
+ ; A[9] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+72]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+192], r10
+ ; A[10] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+80]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+200], r11
+ ; A[11] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+88]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+208], r12
+ ; A[12] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+96]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+216], r10
+ ; A[13] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+104]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+224], r11
+ ; A[14] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+112]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+232], r12
+ ; A[15] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+240], r10
+ mov QWORD PTR [rcx+248], r11
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r10, QWORD PTR [rsp+16]
+ mov r11, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r10, QWORD PTR [rsp+48]
+ mov r11, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r10, QWORD PTR [rsp+80]
+ mov r11, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rsp+96]
+ mov rdx, QWORD PTR [rsp+104]
+ mov r10, QWORD PTR [rsp+112]
+ mov r11, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], rdx
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ add rsp, 128
+ pop r12
+ ret
+sp_2048_mul_16 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sqr_16 PROC
+ push r12
+ push r13
+ push r14
+ mov r8, rdx
+ sub rsp, 128
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ xor r11, r11
+ mov QWORD PTR [rsp], rax
+ mov r10, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+8], r10
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+16], r11
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+8]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+24], r9
+ ; A[0] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+8]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+32], r10
+ ; A[0] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+40], r11
+ ; A[0] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+48], r9
+ ; A[0] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+56], r10
+ ; A[0] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+64], r11
+ ; A[0] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+72], r9
+ ; A[0] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+80], r10
+ ; A[0] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+88], r11
+ ; A[0] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+96], r9
+ ; A[0] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+104], r10
+ ; A[0] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+112], r11
+ ; A[0] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+120], r9
+ ; A[1] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[2] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+128], r10
+ ; A[2] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+16]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[3] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+136], r11
+ ; A[3] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+24]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[4] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+144], r9
+ ; A[4] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+32]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[5] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+152], r10
+ ; A[5] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+40]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[6] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+160], r11
+ ; A[6] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+48]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[7] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+168], r9
+ ; A[7] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+56]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[8] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+176], r10
+ ; A[8] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+64]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[9] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+184], r11
+ ; A[9] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+72]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[10] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[12] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+192], r9
+ ; A[10] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+80]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[11] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[12] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+96]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+200], r10
+ ; A[11] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+88]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[12] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+96]
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[13] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+208], r11
+ ; A[12] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+96]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+104]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+216], r9
+ ; A[13] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+104]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[14] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rcx+224], r10
+ ; A[14] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+112]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+232], r11
+ ; A[15] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul rax
+ add r9, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+240], r9
+ mov QWORD PTR [rcx+248], r10
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r12, QWORD PTR [rsp+16]
+ mov r13, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r12, QWORD PTR [rsp+48]
+ mov r13, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r12
+ mov QWORD PTR [rcx+56], r13
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r12, QWORD PTR [rsp+80]
+ mov r13, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r12
+ mov QWORD PTR [rcx+88], r13
+ mov rax, QWORD PTR [rsp+96]
+ mov rdx, QWORD PTR [rsp+104]
+ mov r12, QWORD PTR [rsp+112]
+ mov r13, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], rdx
+ mov QWORD PTR [rcx+112], r12
+ mov QWORD PTR [rcx+120], r13
+ add rsp, 128
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_sqr_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r Result of multiplication.
+; * a First number to multiply.
+; * b Second number to multiply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_avx2_16 PROC
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ mov rbp, r8
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 128
+ cmp r9, r8
+ mov rbx, rsp
+ cmovne rbx, r8
+ cmp rbp, r8
+ cmove rbx, rsp
+ add r8, 128
+ xor rdi, rdi
+ mov rdx, QWORD PTR [r9]
+ ; A[0] * B[0]
+ mulx r11, r10, QWORD PTR [rbp]
+ ; A[0] * B[1]
+ mulx r12, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx], r10
+ adcx r11, rax
+ ; A[0] * B[2]
+ mulx r13, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+8], r11
+ adcx r12, rax
+ ; A[0] * B[3]
+ mulx r14, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ mov QWORD PTR [rbx+24], r13
+ ; A[0] * B[4]
+ mulx r10, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ ; A[0] * B[5]
+ mulx r11, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ ; A[0] * B[6]
+ mulx r12, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ ; A[0] * B[7]
+ mulx r13, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ mov QWORD PTR [rbx+56], r12
+ ; A[0] * B[8]
+ mulx r14, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ ; A[0] * B[9]
+ mulx r10, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ ; A[0] * B[10]
+ mulx r11, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ ; A[0] * B[11]
+ mulx r12, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ mov QWORD PTR [rbx+88], r11
+ ; A[0] * B[12]
+ mulx r13, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ ; A[0] * B[13]
+ mulx r14, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ ; A[0] * B[14]
+ mulx r10, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ ; A[0] * B[15]
+ mulx r11, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adcx r11, rdi
+ mov r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [rbx+120], r10
+ mov QWORD PTR [r8], r11
+ mov rdx, QWORD PTR [r9+8]
+ mov r11, QWORD PTR [rbx+8]
+ mov r12, QWORD PTR [rbx+16]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ ; A[1] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[1] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[1] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+32], r14
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ ; A[1] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[1] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+64], r13
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[1] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[1] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[1] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[1] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[1] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [rbx+120], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8], r11
+ mov QWORD PTR [r8+8], r12
+ mov rdx, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [rbx+16]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ ; A[2] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[2] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[2] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+40], r10
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ ; A[2] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[2] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+72], r14
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[2] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[2] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[2] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r13
+ mov rdx, QWORD PTR [r9+24]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ ; A[3] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[3] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+48], r11
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ ; A[3] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[3] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+80], r10
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[3] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[3] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+8], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+16], r13
+ mov QWORD PTR [r8+24], r14
+ mov rdx, QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ ; A[4] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+56], r12
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ ; A[4] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+88], r11
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[4] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[4] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[4] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[4] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+16], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+24], r14
+ mov QWORD PTR [r8+32], r10
+ mov rdx, QWORD PTR [r9+40]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ ; A[5] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[5] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+64], r13
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[5] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[5] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[5] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[5] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[5] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[5] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+24], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+32], r10
+ mov QWORD PTR [r8+40], r11
+ mov rdx, QWORD PTR [r9+48]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ ; A[6] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[6] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[6] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+72], r14
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[6] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[6] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[6] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[6] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[6] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[6] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[6] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+32], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+40], r11
+ mov QWORD PTR [r8+48], r12
+ mov rdx, QWORD PTR [r9+56]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ ; A[7] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[7] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[7] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+80], r10
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[7] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[7] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[7] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[7] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[7] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+40], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+48], r12
+ mov QWORD PTR [r8+56], r13
+ mov rdx, QWORD PTR [r9+64]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ ; A[8] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[8] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+88], r11
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[8] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[8] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[8] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r14
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[8] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+48], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+56], r13
+ mov QWORD PTR [r8+64], r14
+ mov rdx, QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[9] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[9] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[9] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[9] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ ; A[9] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[9] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+56], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+64], r14
+ mov QWORD PTR [r8+72], r10
+ mov rdx, QWORD PTR [r9+80]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[10] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[10] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[10] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[10] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[10] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r11
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[10] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[10] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[10] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+64], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+72], r10
+ mov QWORD PTR [r8+80], r11
+ mov rdx, QWORD PTR [r9+88]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[11] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[11] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[11] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[11] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[11] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[11] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[11] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+48], r12
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ ; A[11] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[11] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[11] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+72], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+80], r11
+ mov QWORD PTR [r8+88], r12
+ mov rdx, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[12] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[12] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[12] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[12] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[12] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r14
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ ; A[12] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+56], r13
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ ; A[12] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[12] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+80], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+88], r12
+ mov QWORD PTR [r8+96], r13
+ mov rdx, QWORD PTR [r9+104]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[13] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[13] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[13] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[13] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[13] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+64], r14
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ mov r13, QWORD PTR [r8+96]
+ ; A[13] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+80], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+88], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+96], r13
+ mov QWORD PTR [r8+104], r14
+ mov rdx, QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[14] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[14] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r11
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ ; A[14] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[14] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+72], r10
+ mov r12, QWORD PTR [r8+88]
+ mov r13, QWORD PTR [r8+96]
+ mov r14, QWORD PTR [r8+104]
+ ; A[14] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+80], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[14] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+88], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+96], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+104], r14
+ mov QWORD PTR [r8+112], r10
+ mov rdx, QWORD PTR [r9+120]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[15] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[15] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[15] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+48], r12
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ ; A[15] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[15] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+80], r11
+ mov r13, QWORD PTR [r8+96]
+ mov r14, QWORD PTR [r8+104]
+ mov r10, QWORD PTR [r8+112]
+ ; A[15] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[15] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+88], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[15] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+96], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+104], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r11
+ sub r8, 128
+ cmp r9, r8
+ je L_start_2048_mul_avx2_16
+ cmp rbp, r8
+ jne L_end_2048_mul_avx2_16
+L_start_2048_mul_avx2_16:
+ vmovdqu xmm0, OWORD PTR [rbx]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+48]
+ vmovups OWORD PTR [r8+48], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+64]
+ vmovups OWORD PTR [r8+64], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+80]
+ vmovups OWORD PTR [r8+80], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+96]
+ vmovups OWORD PTR [r8+96], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+112]
+ vmovups OWORD PTR [r8+112], xmm0
+L_end_2048_mul_avx2_16:
+ add rsp, 128
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ pop rbx
+ ret
+sp_2048_mul_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sqr_avx2_16 PROC
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 128
+ cmp r9, r8
+ mov rbp, rsp
+ cmovne rbp, r8
+ add r8, 128
+ xor r13, r13
+ ; Diagonal 1
+ xor r12, r12
+ ; A[1] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx r11, r10, QWORD PTR [r9+8]
+ ; A[2] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+8], r10
+ mov QWORD PTR [rbp+16], r11
+ mov r10, r13
+ mov r11, r13
+ ; A[3] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[4] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+24], r12
+ mov QWORD PTR [rbp+32], r10
+ mov r12, r13
+ mov r10, r13
+ ; A[5] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+40], r11
+ mov QWORD PTR [rbp+48], r12
+ mov r11, r13
+ mov r12, r13
+ ; A[7] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+56], r10
+ mov QWORD PTR [rbp+64], r11
+ mov r10, r13
+ mov r11, r13
+ ; A[9] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[10] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+72], r12
+ mov QWORD PTR [rbp+80], r10
+ mov r12, r13
+ mov r10, r13
+ ; A[11] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+88], r11
+ mov r15, r12
+ mov r11, r13
+ mov r12, r13
+ ; A[13] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r11, rax
+ adox r12, rcx
+ mov rdi, r10
+ mov rsi, r11
+ mov r10, r13
+ ; A[15] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r10, rcx
+ mov rbx, r12
+ ; Carry
+ adcx r10, r13
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8], r10
+ ; Diagonal 2
+ mov r10, QWORD PTR [rbp+24]
+ mov r11, QWORD PTR [rbp+32]
+ mov r12, QWORD PTR [rbp+40]
+ ; A[2] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+24], r10
+ mov QWORD PTR [rbp+32], r11
+ mov r10, QWORD PTR [rbp+48]
+ mov r11, QWORD PTR [rbp+56]
+ ; A[4] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[5] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+40], r12
+ mov QWORD PTR [rbp+48], r10
+ mov r12, QWORD PTR [rbp+64]
+ mov r10, QWORD PTR [rbp+72]
+ ; A[6] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+56], r11
+ mov QWORD PTR [rbp+64], r12
+ mov r11, QWORD PTR [rbp+80]
+ mov r12, QWORD PTR [rbp+88]
+ ; A[8] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+72], r10
+ mov QWORD PTR [rbp+80], r11
+ ; No load %r13 - %r8
+ ; No load %r14 - %r9
+ ; A[10] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r12, rax
+ adox r15, rcx
+ ; A[11] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r12
+ ; No store %r13
+ ; No load %r15 - %r10
+ ; No load %rbx - %r8
+ ; A[12] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[13] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ mov r12, r13
+ ; A[14] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[15] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, r13
+ ; A[15] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+16], r10
+ ; Diagonal 3
+ mov r10, QWORD PTR [rbp+40]
+ mov r11, QWORD PTR [rbp+48]
+ mov r12, QWORD PTR [rbp+56]
+ ; A[3] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+40], r10
+ mov QWORD PTR [rbp+48], r11
+ mov r10, QWORD PTR [rbp+64]
+ mov r11, QWORD PTR [rbp+72]
+ ; A[5] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[6] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+56], r12
+ mov QWORD PTR [rbp+64], r10
+ mov r12, QWORD PTR [rbp+80]
+ mov r10, QWORD PTR [rbp+88]
+ ; A[7] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+72], r11
+ mov QWORD PTR [rbp+80], r12
+ ; No load %r13 - %r9
+ ; No load %r14 - %r10
+ ; A[9] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r15, rcx
+ ; A[10] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r10
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; No load %rbx - %r9
+ ; A[11] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[12] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ ; A[13] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx rbx, rax
+ adox r12, rcx
+ ; A[14] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r12, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r12
+ mov r11, QWORD PTR [r8+16]
+ mov r12, r13
+ ; A[14] x A[3]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r10
+ mov QWORD PTR [r8+16], r11
+ mov r10, r13
+ ; A[14] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+32], r10
+ ; Diagonal 4
+ mov r10, QWORD PTR [rbp+56]
+ mov r11, QWORD PTR [rbp+64]
+ mov r12, QWORD PTR [rbp+72]
+ ; A[4] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+56], r10
+ mov QWORD PTR [rbp+64], r11
+ mov r10, QWORD PTR [rbp+80]
+ mov r11, QWORD PTR [rbp+88]
+ ; A[6] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[7] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+72], r12
+ mov QWORD PTR [rbp+80], r10
+ ; No load %r13 - %r10
+ ; No load %r14 - %r8
+ ; A[8] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r15, rcx
+ ; A[9] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r11
+ ; No store %r13
+ ; No load %r15 - %r9
+ ; No load %rbx - %r10
+ ; A[10] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[11] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[12] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rbx, rax
+ adox r10, rcx
+ ; A[13] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r10, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[13] x A[4]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, r13
+ ; A[13] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+24], r10
+ mov QWORD PTR [r8+32], r11
+ mov r10, r13
+ ; A[13] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+48], r10
+ ; Diagonal 5
+ mov r10, QWORD PTR [rbp+72]
+ mov r11, QWORD PTR [rbp+80]
+ mov r12, QWORD PTR [rbp+88]
+ ; A[5] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+72], r10
+ mov QWORD PTR [rbp+80], r11
+ ; No load %r13 - %r8
+ ; No load %r14 - %r9
+ ; A[7] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r15, rcx
+ ; A[8] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r12
+ ; No store %r13
+ ; No load %r15 - %r10
+ ; No load %rbx - %r8
+ ; A[9] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[10] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[11] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[12] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[12] x A[5]
+ mov rdx, QWORD PTR [r9+96]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[12] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r10
+ mov r12, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [r8+40]
+ ; A[12] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov QWORD PTR [r8+32], r12
+ mov r11, QWORD PTR [r8+48]
+ mov r12, r13
+ ; A[12] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r10
+ mov QWORD PTR [r8+48], r11
+ mov r10, r13
+ ; A[12] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+56], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+64], r10
+ ; Diagonal 6
+ mov r10, QWORD PTR [rbp+88]
+ ; No load %r13 - %r9
+ ; No load %r14 - %r10
+ ; A[6] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r15, rcx
+ ; A[7] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r10
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; No load %rbx - %r9
+ ; A[8] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[9] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ ; A[10] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rbx, rax
+ adox r12, rcx
+ ; A[11] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r12
+ mov r11, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [r8+24]
+ ; A[11] x A[6]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r10
+ mov QWORD PTR [r8+16], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[11] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[11] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r12
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [r8+56]
+ ; A[11] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] x A[9]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r11
+ mov QWORD PTR [r8+48], r12
+ mov r11, QWORD PTR [r8+64]
+ mov r12, r13
+ ; A[13] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+56], r10
+ mov QWORD PTR [r8+64], r11
+ mov r10, r13
+ ; A[13] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+72], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+80], r10
+ ; Diagonal 7
+ ; No load %r14 - %r8
+ ; No load %r15 - %r9
+ ; No load %rbx - %r10
+ ; A[7] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[8] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[9] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rbx, rax
+ adox r10, rcx
+ ; A[10] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[10] x A[7]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, QWORD PTR [r8+40]
+ ; A[10] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[6]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+24], r10
+ mov QWORD PTR [r8+32], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[14] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[14] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+40], r12
+ mov QWORD PTR [r8+48], r10
+ mov r12, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[14] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+56], r11
+ mov QWORD PTR [r8+64], r12
+ mov r11, QWORD PTR [r8+80]
+ mov r12, r13
+ ; A[14] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+72], r10
+ mov QWORD PTR [r8+80], r11
+ mov r10, r13
+ ; A[14] x A[13]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+88], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+96], r10
+ ; Diagonal 8
+ ; No load %rbx - %r8
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[8] x A[7]
+ mov rdx, QWORD PTR [r9+56]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[9] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[9] x A[8]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[15] x A[3]
+ mov rdx, QWORD PTR [r9+120]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r10
+ mov r12, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [r8+40]
+ ; A[15] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov QWORD PTR [r8+32], r12
+ mov r11, QWORD PTR [r8+48]
+ mov r12, QWORD PTR [r8+56]
+ ; A[15] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r10
+ mov QWORD PTR [r8+48], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ ; A[15] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[15] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+56], r12
+ mov QWORD PTR [r8+64], r10
+ mov r12, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [r8+88]
+ ; A[15] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+72], r11
+ mov QWORD PTR [r8+80], r12
+ mov r11, QWORD PTR [r8+96]
+ mov r12, r13
+ ; A[15] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] x A[13]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+88], r10
+ mov QWORD PTR [r8+96], r11
+ mov r10, r13
+ ; A[15] x A[14]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+104], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r14
+ ; Double and Add in A[i] x A[i]
+ mov r11, QWORD PTR [rbp+8]
+ ; A[0] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx rcx, rax, rdx
+ mov QWORD PTR [rbp], rax
+ adox r11, r11
+ adcx r11, rcx
+ mov QWORD PTR [rbp+8], r11
+ mov r10, QWORD PTR [rbp+16]
+ mov r11, QWORD PTR [rbp+24]
+ ; A[1] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+16], r10
+ mov QWORD PTR [rbp+24], r11
+ mov r10, QWORD PTR [rbp+32]
+ mov r11, QWORD PTR [rbp+40]
+ ; A[2] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+32], r10
+ mov QWORD PTR [rbp+40], r11
+ mov r10, QWORD PTR [rbp+48]
+ mov r11, QWORD PTR [rbp+56]
+ ; A[3] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+48], r10
+ mov QWORD PTR [rbp+56], r11
+ mov r10, QWORD PTR [rbp+64]
+ mov r11, QWORD PTR [rbp+72]
+ ; A[4] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+64], r10
+ mov QWORD PTR [rbp+72], r11
+ mov r10, QWORD PTR [rbp+80]
+ mov r11, QWORD PTR [rbp+88]
+ ; A[5] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+80], r10
+ mov QWORD PTR [rbp+88], r11
+ ; A[6] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, rdx
+ adox r15, r15
+ adox rdi, rdi
+ adcx r15, rax
+ adcx rdi, rcx
+ ; A[7] x A[7]
+ mov rdx, QWORD PTR [r9+56]
+ mulx rcx, rax, rdx
+ adox rsi, rsi
+ adox rbx, rbx
+ adcx rsi, rax
+ adcx rbx, rcx
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[8] x A[8]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8], r10
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[9] x A[9]
+ mov rdx, QWORD PTR [r9+72]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+16], r10
+ mov QWORD PTR [r8+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[10] x A[10]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov QWORD PTR [r8+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[11] x A[11]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov QWORD PTR [r8+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ ; A[12] x A[12]
+ mov rdx, QWORD PTR [r9+96]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+64], r10
+ mov QWORD PTR [r8+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ ; A[13] x A[13]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+80], r10
+ mov QWORD PTR [r8+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ ; A[14] x A[14]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+96], r10
+ mov QWORD PTR [r8+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ ; A[15] x A[15]
+ mov rdx, QWORD PTR [r9+120]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r11
+ mov QWORD PTR [r8+-32], r15
+ mov QWORD PTR [r8+-24], rdi
+ mov QWORD PTR [r8+-16], rsi
+ mov QWORD PTR [r8+-8], rbx
+ sub r8, 128
+ cmp r9, r8
+ jne L_end_2048_sqr_avx2_16
+ vmovdqu xmm0, OWORD PTR [rbp]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+48]
+ vmovups OWORD PTR [r8+48], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+64]
+ vmovups OWORD PTR [r8+64], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+80]
+ vmovups OWORD PTR [r8+80], xmm0
+L_end_2048_sqr_avx2_16:
+ add rsp, 128
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ ret
+sp_2048_sqr_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_add_16 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+120], r10
+ adc rax, 0
+ ret
+sp_2048_add_16 ENDP
+_text ENDS
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sub_in_place_32 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rcx+120], r9
+ sbb r8, QWORD PTR [rdx+128]
+ mov r9, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], r8
+ sbb r9, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r9
+ sbb r8, QWORD PTR [rdx+144]
+ mov r9, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], r8
+ sbb r9, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r9
+ sbb r8, QWORD PTR [rdx+160]
+ mov r9, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], r8
+ sbb r9, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r9
+ sbb r8, QWORD PTR [rdx+176]
+ mov r9, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], r8
+ sbb r9, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rcx+184], r9
+ sbb r8, QWORD PTR [rdx+192]
+ mov r9, QWORD PTR [rcx+200]
+ mov QWORD PTR [rcx+192], r8
+ sbb r9, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rcx+200], r9
+ sbb r8, QWORD PTR [rdx+208]
+ mov r9, QWORD PTR [rcx+216]
+ mov QWORD PTR [rcx+208], r8
+ sbb r9, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rcx+216], r9
+ sbb r8, QWORD PTR [rdx+224]
+ mov r9, QWORD PTR [rcx+232]
+ mov QWORD PTR [rcx+224], r8
+ sbb r9, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rcx+232], r9
+ sbb r8, QWORD PTR [rdx+240]
+ mov r9, QWORD PTR [rcx+248]
+ mov QWORD PTR [rcx+240], r8
+ sbb r9, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+248], r9
+ sbb rax, 0
+ ret
+sp_2048_sub_in_place_32 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_add_32 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ adc r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ adc r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ adc r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ adc r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ adc r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ adc r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ adc r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ adc r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ adc r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ adc r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ adc r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ adc r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ adc r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ adc r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ adc r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ adc r10, QWORD PTR [r8+248]
+ mov QWORD PTR [rcx+248], r10
+ adc rax, 0
+ ret
+sp_2048_add_32 ENDP
+_text ENDS
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_32 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 808
+ mov QWORD PTR [rsp+768], rcx
+ mov QWORD PTR [rsp+776], rdx
+ mov QWORD PTR [rsp+784], r8
+ lea r12, QWORD PTR [rsp+512]
+ lea r14, QWORD PTR [rdx+128]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov QWORD PTR [r12+120], rax
+ adc r15, 0
+ mov QWORD PTR [rsp+792], r15
+ lea r13, QWORD PTR [rsp+640]
+ lea r14, QWORD PTR [r8+128]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov QWORD PTR [r13+120], rax
+ adc rdi, 0
+ mov QWORD PTR [rsp+800], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_2048_mul_16
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ lea rcx, QWORD PTR [rsp+256]
+ add r8, 128
+ add rdx, 128
+ call sp_2048_mul_16
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ mov rcx, QWORD PTR [rsp+768]
+ call sp_2048_mul_16
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ mov rcx, QWORD PTR [rsp+768]
+ENDIF
+ mov r15, QWORD PTR [rsp+792]
+ mov rdi, QWORD PTR [rsp+800]
+ mov rsi, QWORD PTR [rsp+768]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+512]
+ lea r13, QWORD PTR [rsp+640]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 256
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12], rax
+ mov QWORD PTR [r13], r9
+ mov rax, QWORD PTR [r12+8]
+ mov r9, QWORD PTR [r13+8]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+8], rax
+ mov QWORD PTR [r13+8], r9
+ mov rax, QWORD PTR [r12+16]
+ mov r9, QWORD PTR [r13+16]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+16], rax
+ mov QWORD PTR [r13+16], r9
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+24], rax
+ mov QWORD PTR [r13+24], r9
+ mov rax, QWORD PTR [r12+32]
+ mov r9, QWORD PTR [r13+32]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+32], rax
+ mov QWORD PTR [r13+32], r9
+ mov rax, QWORD PTR [r12+40]
+ mov r9, QWORD PTR [r13+40]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+40], rax
+ mov QWORD PTR [r13+40], r9
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+48], rax
+ mov QWORD PTR [r13+48], r9
+ mov rax, QWORD PTR [r12+56]
+ mov r9, QWORD PTR [r13+56]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+56], rax
+ mov QWORD PTR [r13+56], r9
+ mov rax, QWORD PTR [r12+64]
+ mov r9, QWORD PTR [r13+64]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+64], rax
+ mov QWORD PTR [r13+64], r9
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+72], rax
+ mov QWORD PTR [r13+72], r9
+ mov rax, QWORD PTR [r12+80]
+ mov r9, QWORD PTR [r13+80]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+80], rax
+ mov QWORD PTR [r13+80], r9
+ mov rax, QWORD PTR [r12+88]
+ mov r9, QWORD PTR [r13+88]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+88], rax
+ mov QWORD PTR [r13+88], r9
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+96], rax
+ mov QWORD PTR [r13+96], r9
+ mov rax, QWORD PTR [r12+104]
+ mov r9, QWORD PTR [r13+104]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+104], rax
+ mov QWORD PTR [r13+104], r9
+ mov rax, QWORD PTR [r12+112]
+ mov r9, QWORD PTR [r13+112]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+112], rax
+ mov QWORD PTR [r13+112], r9
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+120], rax
+ mov QWORD PTR [r13+120], r9
+ mov rax, QWORD PTR [r12]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov QWORD PTR [rsi+120], rax
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+256]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov QWORD PTR [r12+248], r9
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov QWORD PTR [r12+248], r9
+ sbb r11, 0
+ sub rsi, 128
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov QWORD PTR [rsi+248], r9
+ adc r11, 0
+ mov QWORD PTR [rcx+384], r11
+ add rsi, 128
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ xor r11, r11
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov QWORD PTR [rsi+128], r9
+ adc r11, 0
+ ; Add to zero
+ mov rax, QWORD PTR [r13+136]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+144]
+ mov QWORD PTR [rsi+136], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+152]
+ mov QWORD PTR [rsi+144], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+160]
+ mov QWORD PTR [rsi+152], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+168]
+ mov QWORD PTR [rsi+160], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+176]
+ mov QWORD PTR [rsi+168], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+184]
+ mov QWORD PTR [rsi+176], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+192]
+ mov QWORD PTR [rsi+184], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+200]
+ mov QWORD PTR [rsi+192], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+208]
+ mov QWORD PTR [rsi+200], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+216]
+ mov QWORD PTR [rsi+208], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+224]
+ mov QWORD PTR [rsi+216], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+232]
+ mov QWORD PTR [rsi+224], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+240]
+ mov QWORD PTR [rsi+232], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+248]
+ mov QWORD PTR [rsi+240], r9
+ adc r10, 0
+ mov QWORD PTR [rsi+248], r10
+ add rsp, 808
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mul_32 ENDP
+_text ENDS
+; /* Add a to a into r. (r = a + a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_dbl_16 PROC
+ mov r8, QWORD PTR [rdx]
+ xor rax, rax
+ add r8, r8
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r8
+ adc r9, r9
+ mov QWORD PTR [rcx+120], r9
+ adc rax, 0
+ ret
+sp_2048_dbl_16 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sqr_32 PROC
+ push r12
+ sub rsp, 664
+ mov QWORD PTR [rsp+640], rcx
+ mov QWORD PTR [rsp+648], rdx
+ lea r10, QWORD PTR [rsp+512]
+ lea r11, QWORD PTR [rdx+128]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r10+120], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+656], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_2048_sqr_16
+ mov rdx, QWORD PTR [rsp+648]
+ lea rcx, QWORD PTR [rsp+256]
+ add rdx, 128
+ call sp_2048_sqr_16
+ mov rdx, QWORD PTR [rsp+648]
+ mov rcx, QWORD PTR [rsp+640]
+ call sp_2048_sqr_16
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+648]
+ mov rcx, QWORD PTR [rsp+640]
+ENDIF
+ mov r12, QWORD PTR [rsp+656]
+ lea r10, QWORD PTR [rsp+512]
+ mov r9, r12
+ neg r12
+ mov rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r10+8]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+256], rax
+ mov QWORD PTR [rcx+264], r8
+ mov rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r10+24]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+272], rax
+ mov QWORD PTR [rcx+280], r8
+ mov rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r10+40]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+288], rax
+ mov QWORD PTR [rcx+296], r8
+ mov rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r10+56]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+304], rax
+ mov QWORD PTR [rcx+312], r8
+ mov rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r10+72]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+320], rax
+ mov QWORD PTR [rcx+328], r8
+ mov rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r10+88]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+336], rax
+ mov QWORD PTR [rcx+344], r8
+ mov rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r10+104]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+352], rax
+ mov QWORD PTR [rcx+360], r8
+ mov rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r10+120]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+368], rax
+ mov QWORD PTR [rcx+376], r8
+ mov rax, QWORD PTR [rcx+256]
+ add rax, rax
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, r8
+ mov QWORD PTR [rcx+376], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+256]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov QWORD PTR [r10+248], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov QWORD PTR [r10+248], r8
+ sbb r9, 0
+ ; Add in place
+ mov rax, QWORD PTR [rcx+128]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [rcx+192]
+ mov QWORD PTR [rcx+184], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [rcx+200]
+ mov QWORD PTR [rcx+192], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [rcx+208]
+ mov QWORD PTR [rcx+200], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [rcx+216]
+ mov QWORD PTR [rcx+208], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [rcx+224]
+ mov QWORD PTR [rcx+216], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [rcx+232]
+ mov QWORD PTR [rcx+224], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [rcx+240]
+ mov QWORD PTR [rcx+232], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [rcx+248]
+ mov QWORD PTR [rcx+240], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [rcx+256]
+ mov QWORD PTR [rcx+248], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [r10+248]
+ mov QWORD PTR [rcx+376], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+384], r9
+ ; Add in place
+ mov rax, QWORD PTR [rcx+256]
+ xor r9, r9
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rcx+384]
+ mov QWORD PTR [rcx+376], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+384], rax
+ adc r9, 0
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+136]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+392], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+400], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+408], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+416], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+424], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+432], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+440], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+448], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+456], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+464], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+472], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+480], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+488], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+496], r8
+ adc rax, 0
+ mov QWORD PTR [rcx+504], rax
+ add rsp, 664
+ pop r12
+ ret
+sp_2048_sqr_32 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_avx2_32 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 808
+ mov QWORD PTR [rsp+768], rcx
+ mov QWORD PTR [rsp+776], rdx
+ mov QWORD PTR [rsp+784], r8
+ lea r12, QWORD PTR [rsp+512]
+ lea r14, QWORD PTR [rdx+128]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov QWORD PTR [r12+120], rax
+ adc r15, 0
+ mov QWORD PTR [rsp+792], r15
+ lea r13, QWORD PTR [rsp+640]
+ lea r14, QWORD PTR [r8+128]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov QWORD PTR [r13+120], rax
+ adc rdi, 0
+ mov QWORD PTR [rsp+800], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_2048_mul_avx2_16
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ lea rcx, QWORD PTR [rsp+256]
+ add r8, 128
+ add rdx, 128
+ call sp_2048_mul_avx2_16
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ mov rcx, QWORD PTR [rsp+768]
+ call sp_2048_mul_avx2_16
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+784]
+ mov rdx, QWORD PTR [rsp+776]
+ mov rcx, QWORD PTR [rsp+768]
+ENDIF
+ mov r15, QWORD PTR [rsp+792]
+ mov rdi, QWORD PTR [rsp+800]
+ mov rsi, QWORD PTR [rsp+768]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+512]
+ lea r13, QWORD PTR [rsp+640]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 256
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ add rax, r9
+ mov r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [r13+8]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [r13+16]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+8], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+16], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [r13+32]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+24], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [r13+40]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+32], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+40], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [r13+56]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+48], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [r13+64]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+56], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+64], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [r13+80]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+72], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [r13+88]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+80], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+88], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [r13+104]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+96], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [r13+112]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+104], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+112], r10
+ adc rax, r9
+ mov QWORD PTR [rsi+120], rax
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+256]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov QWORD PTR [r12+248], r9
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov QWORD PTR [r12+248], r9
+ sbb r11, 0
+ sub rsi, 128
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov QWORD PTR [rsi+248], r9
+ adc r11, 0
+ mov QWORD PTR [rcx+384], r11
+ add rsi, 128
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ xor r11, r11
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov QWORD PTR [rsi+128], r9
+ adc r11, 0
+ ; Add to zero
+ mov rax, QWORD PTR [r13+136]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+144]
+ mov QWORD PTR [rsi+136], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+152]
+ mov QWORD PTR [rsi+144], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+160]
+ mov QWORD PTR [rsi+152], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+168]
+ mov QWORD PTR [rsi+160], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+176]
+ mov QWORD PTR [rsi+168], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+184]
+ mov QWORD PTR [rsi+176], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+192]
+ mov QWORD PTR [rsi+184], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+200]
+ mov QWORD PTR [rsi+192], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+208]
+ mov QWORD PTR [rsi+200], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+216]
+ mov QWORD PTR [rsi+208], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+224]
+ mov QWORD PTR [rsi+216], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+232]
+ mov QWORD PTR [rsi+224], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+240]
+ mov QWORD PTR [rsi+232], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+248]
+ mov QWORD PTR [rsi+240], r9
+ adc r10, 0
+ mov QWORD PTR [rsi+248], r10
+ add rsp, 808
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mul_avx2_32 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sqr_avx2_32 PROC
+ push r12
+ sub rsp, 664
+ mov QWORD PTR [rsp+640], rcx
+ mov QWORD PTR [rsp+648], rdx
+ lea r10, QWORD PTR [rsp+512]
+ lea r11, QWORD PTR [rdx+128]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r10+120], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+656], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_2048_sqr_avx2_16
+ mov rdx, QWORD PTR [rsp+648]
+ lea rcx, QWORD PTR [rsp+256]
+ add rdx, 128
+ call sp_2048_sqr_avx2_16
+ mov rdx, QWORD PTR [rsp+648]
+ mov rcx, QWORD PTR [rsp+640]
+ call sp_2048_sqr_avx2_16
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+648]
+ mov rcx, QWORD PTR [rsp+640]
+ENDIF
+ mov r12, QWORD PTR [rsp+656]
+ lea r10, QWORD PTR [rsp+512]
+ mov r9, r12
+ neg r12
+ mov rax, QWORD PTR [r10]
+ pext rax, rax, r12
+ add rax, rax
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [rcx+256], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [rcx+264], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [rcx+272], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [rcx+280], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [rcx+288], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [rcx+296], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [rcx+304], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [rcx+312], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [rcx+320], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [rcx+328], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [rcx+336], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [rcx+344], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [rcx+352], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [rcx+360], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [rcx+368], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov QWORD PTR [rcx+376], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+256]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov QWORD PTR [r10+248], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov QWORD PTR [r10+248], r8
+ sbb r9, 0
+ ; Add in place
+ mov rax, QWORD PTR [rcx+128]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [rcx+192]
+ mov QWORD PTR [rcx+184], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [rcx+200]
+ mov QWORD PTR [rcx+192], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [rcx+208]
+ mov QWORD PTR [rcx+200], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [rcx+216]
+ mov QWORD PTR [rcx+208], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [rcx+224]
+ mov QWORD PTR [rcx+216], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [rcx+232]
+ mov QWORD PTR [rcx+224], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [rcx+240]
+ mov QWORD PTR [rcx+232], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [rcx+248]
+ mov QWORD PTR [rcx+240], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [rcx+256]
+ mov QWORD PTR [rcx+248], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [r10+248]
+ mov QWORD PTR [rcx+376], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+384], r9
+ ; Add in place
+ mov rax, QWORD PTR [rcx+256]
+ xor r9, r9
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rcx+384]
+ mov QWORD PTR [rcx+376], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+384], rax
+ adc r9, 0
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+136]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+392], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+400], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+408], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+416], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+424], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+432], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+440], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+448], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+456], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+464], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+472], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+480], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+488], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+496], r8
+ adc rax, 0
+ mov QWORD PTR [rcx+504], rax
+ add rsp, 664
+ pop r12
+ ret
+sp_2048_sqr_avx2_32 ENDP
+_text ENDS
+ENDIF
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sub_in_place_16 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+120], r9
+ sbb rax, 0
+ ret
+sp_2048_sub_in_place_16 ENDP
+_text ENDS
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_d_32 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ mov QWORD PTR [rcx+120], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[16] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+128]
+ add r11, rax
+ mov QWORD PTR [rcx+128], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[17] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ add r12, rax
+ mov QWORD PTR [rcx+136], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[18] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ add r10, rax
+ mov QWORD PTR [rcx+144], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[19] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+152]
+ add r11, rax
+ mov QWORD PTR [rcx+152], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[20] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+160]
+ add r12, rax
+ mov QWORD PTR [rcx+160], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[21] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+168]
+ add r10, rax
+ mov QWORD PTR [rcx+168], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[22] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+176]
+ add r11, rax
+ mov QWORD PTR [rcx+176], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[23] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ add r12, rax
+ mov QWORD PTR [rcx+184], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[24] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ add r10, rax
+ mov QWORD PTR [rcx+192], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[25] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+200]
+ add r11, rax
+ mov QWORD PTR [rcx+200], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[26] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+208]
+ add r12, rax
+ mov QWORD PTR [rcx+208], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[27] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+216]
+ add r10, rax
+ mov QWORD PTR [rcx+216], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[28] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+224]
+ add r11, rax
+ mov QWORD PTR [rcx+224], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[29] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ add r12, rax
+ mov QWORD PTR [rcx+232], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[30] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ add r10, rax
+ mov QWORD PTR [rcx+240], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[31] * B
+ mov rax, r8
+ mul QWORD PTR [r9+248]
+ add r11, rax
+ adc r12, rdx
+ mov QWORD PTR [rcx+248], r11
+ mov QWORD PTR [rcx+256], r12
+ pop r12
+ ret
+sp_2048_mul_d_32 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_sub_16 PROC
+ sub rsp, 128
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb rax, 0
+ add rsp, 128
+ ret
+sp_2048_cond_sub_16 ENDP
+_text ENDS
+; /* Reduce the number back to 2048 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mont_reduce_16 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 16
+ mov r10, 16
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_2048_mont_loop_16:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc QWORD PTR [rcx+128], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_2048_mont_loop_16
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 128
+ call sp_2048_cond_sub_16
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mont_reduce_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_sub_avx2_16 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov QWORD PTR [rcx+120], r10
+ sbb rax, 0
+ pop r12
+ ret
+sp_2048_cond_sub_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_d_16 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+120], r10
+ mov QWORD PTR [rcx+128], r11
+ pop r12
+ ret
+sp_2048_mul_d_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_d_avx2_16 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+120], r12
+ mov QWORD PTR [rcx+128], r11
+ pop r13
+ pop r12
+ ret
+sp_2048_mul_d_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_2048_word_asm_16 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_2048_word_asm_16 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cmp_16 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_2048_cmp_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 2048 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mont_reduce_avx2_16 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 16
+ mov r11, 16
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 64
+ xor rbp, rbp
+L_2048_mont_loop_avx2_16:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-32]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-24]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+64], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-24]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-16]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-8]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-16], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-8], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+8]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+16]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+8], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+24]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+16], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+32]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+24], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+40]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+32], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+40], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+56]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+48], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+56], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+72]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+64], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+72], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 2
+ add r9, 16
+ ; i -= 2
+ sub r11, 2
+ jnz L_2048_mont_loop_avx2_16
+ sub r9, 64
+ neg rbp
+ mov r8, r9
+ sub r9, 128
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov QWORD PTR [r9+120], rdx
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mont_reduce_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_sub_32 PROC
+ sub rsp, 256
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [r8+192]
+ mov r11, QWORD PTR [r8+200]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+192], r10
+ mov QWORD PTR [rsp+200], r11
+ mov r10, QWORD PTR [r8+208]
+ mov r11, QWORD PTR [r8+216]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+208], r10
+ mov QWORD PTR [rsp+216], r11
+ mov r10, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [r8+232]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+224], r10
+ mov QWORD PTR [rsp+232], r11
+ mov r10, QWORD PTR [r8+240]
+ mov r11, QWORD PTR [r8+248]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+240], r10
+ mov QWORD PTR [rsp+248], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ sbb r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ sbb r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ sbb r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ sbb r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ sbb r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ sbb r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ sbb r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ sbb r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov r10, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rsp+192]
+ sbb r10, r8
+ mov QWORD PTR [rcx+184], r11
+ mov r11, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rsp+200]
+ sbb r11, r8
+ mov QWORD PTR [rcx+192], r10
+ mov r10, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rsp+208]
+ sbb r10, r8
+ mov QWORD PTR [rcx+200], r11
+ mov r11, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rsp+216]
+ sbb r11, r8
+ mov QWORD PTR [rcx+208], r10
+ mov r10, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rsp+224]
+ sbb r10, r8
+ mov QWORD PTR [rcx+216], r11
+ mov r11, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rsp+232]
+ sbb r11, r8
+ mov QWORD PTR [rcx+224], r10
+ mov r10, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rsp+240]
+ sbb r10, r8
+ mov QWORD PTR [rcx+232], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rsp+248]
+ sbb r11, r8
+ mov QWORD PTR [rcx+240], r10
+ mov QWORD PTR [rcx+248], r11
+ sbb rax, 0
+ add rsp, 256
+ ret
+sp_2048_cond_sub_32 ENDP
+_text ENDS
+; /* Reduce the number back to 2048 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mont_reduce_32 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 32
+ mov r10, 32
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_2048_mont_loop_32:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc r11, 0
+ ; a[i+16] += m[16] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+128]
+ mov r14, QWORD PTR [rcx+128]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+128], r14
+ adc r12, 0
+ ; a[i+17] += m[17] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ mov r14, QWORD PTR [rcx+136]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+136], r14
+ adc r11, 0
+ ; a[i+18] += m[18] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ mov r14, QWORD PTR [rcx+144]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+144], r14
+ adc r12, 0
+ ; a[i+19] += m[19] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+152]
+ mov r14, QWORD PTR [rcx+152]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+152], r14
+ adc r11, 0
+ ; a[i+20] += m[20] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+160]
+ mov r14, QWORD PTR [rcx+160]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+160], r14
+ adc r12, 0
+ ; a[i+21] += m[21] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+168]
+ mov r14, QWORD PTR [rcx+168]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+168], r14
+ adc r11, 0
+ ; a[i+22] += m[22] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+176]
+ mov r14, QWORD PTR [rcx+176]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+176], r14
+ adc r12, 0
+ ; a[i+23] += m[23] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ mov r14, QWORD PTR [rcx+184]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+184], r14
+ adc r11, 0
+ ; a[i+24] += m[24] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ mov r14, QWORD PTR [rcx+192]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+192], r14
+ adc r12, 0
+ ; a[i+25] += m[25] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+200]
+ mov r14, QWORD PTR [rcx+200]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+200], r14
+ adc r11, 0
+ ; a[i+26] += m[26] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+208]
+ mov r14, QWORD PTR [rcx+208]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+208], r14
+ adc r12, 0
+ ; a[i+27] += m[27] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+216]
+ mov r14, QWORD PTR [rcx+216]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+216], r14
+ adc r11, 0
+ ; a[i+28] += m[28] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+224]
+ mov r14, QWORD PTR [rcx+224]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+224], r14
+ adc r12, 0
+ ; a[i+29] += m[29] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ mov r14, QWORD PTR [rcx+232]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+232], r14
+ adc r11, 0
+ ; a[i+30] += m[30] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ mov r14, QWORD PTR [rcx+240]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+240], r14
+ adc r12, 0
+ ; a[i+31] += m[31] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+248]
+ mov r14, QWORD PTR [rcx+248]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+248], r14
+ adc QWORD PTR [rcx+256], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_2048_mont_loop_32
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 256
+ call sp_2048_cond_sub_32
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mont_reduce_32 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_sub_avx2_32 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+192]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+184], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+200]
+ mov r11, QWORD PTR [rdx+200]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+192], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+208]
+ mov r12, QWORD PTR [rdx+208]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+200], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+216]
+ mov r10, QWORD PTR [rdx+216]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+208], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [rdx+224]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+216], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+232]
+ mov r12, QWORD PTR [rdx+232]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+224], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+240]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+232], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+248]
+ mov r11, QWORD PTR [rdx+248]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+240], r10
+ sbb r11, r12
+ mov QWORD PTR [rcx+248], r11
+ sbb rax, 0
+ pop r12
+ ret
+sp_2048_cond_sub_avx2_32 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mul_d_avx2_32 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+120], r12
+ ; A[16] * B
+ mulx r10, r9, QWORD PTR [rax+128]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+128], r11
+ ; A[17] * B
+ mulx r10, r9, QWORD PTR [rax+136]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+136], r12
+ ; A[18] * B
+ mulx r10, r9, QWORD PTR [rax+144]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+144], r11
+ ; A[19] * B
+ mulx r10, r9, QWORD PTR [rax+152]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+152], r12
+ ; A[20] * B
+ mulx r10, r9, QWORD PTR [rax+160]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+160], r11
+ ; A[21] * B
+ mulx r10, r9, QWORD PTR [rax+168]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+168], r12
+ ; A[22] * B
+ mulx r10, r9, QWORD PTR [rax+176]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+176], r11
+ ; A[23] * B
+ mulx r10, r9, QWORD PTR [rax+184]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+184], r12
+ ; A[24] * B
+ mulx r10, r9, QWORD PTR [rax+192]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+192], r11
+ ; A[25] * B
+ mulx r10, r9, QWORD PTR [rax+200]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+200], r12
+ ; A[26] * B
+ mulx r10, r9, QWORD PTR [rax+208]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+208], r11
+ ; A[27] * B
+ mulx r10, r9, QWORD PTR [rax+216]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+216], r12
+ ; A[28] * B
+ mulx r10, r9, QWORD PTR [rax+224]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+224], r11
+ ; A[29] * B
+ mulx r10, r9, QWORD PTR [rax+232]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+232], r12
+ ; A[30] * B
+ mulx r10, r9, QWORD PTR [rax+240]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+240], r11
+ ; A[31] * B
+ mulx r10, r9, QWORD PTR [rax+248]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+248], r12
+ mov QWORD PTR [rcx+256], r11
+ pop r13
+ pop r12
+ ret
+sp_2048_mul_d_avx2_32 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_2048_word_asm_32 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_2048_word_asm_32 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cmp_32 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+248]
+ mov r12, QWORD PTR [rdx+248]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+240]
+ mov r12, QWORD PTR [rdx+240]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+232]
+ mov r12, QWORD PTR [rdx+232]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+224]
+ mov r12, QWORD PTR [rdx+224]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+216]
+ mov r12, QWORD PTR [rdx+216]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+208]
+ mov r12, QWORD PTR [rdx+208]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+200]
+ mov r12, QWORD PTR [rdx+200]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+192]
+ mov r12, QWORD PTR [rdx+192]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+184]
+ mov r12, QWORD PTR [rdx+184]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+176]
+ mov r12, QWORD PTR [rdx+176]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+168]
+ mov r12, QWORD PTR [rdx+168]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+160]
+ mov r12, QWORD PTR [rdx+160]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+152]
+ mov r12, QWORD PTR [rdx+152]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+144]
+ mov r12, QWORD PTR [rdx+144]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+136]
+ mov r12, QWORD PTR [rdx+136]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+128]
+ mov r12, QWORD PTR [rdx+128]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_2048_cmp_32 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_sub_32 PROC
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ sub r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ sbb r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ sbb r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ sbb r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ sbb r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ sbb r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ sbb r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ sbb r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ sbb r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ sbb r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ sbb r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ sbb r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ sbb r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ sbb r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ sbb r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ sbb r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ sbb r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ sbb r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ sbb r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ sbb r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ sbb r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ sbb r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ sbb r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ sbb r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ sbb r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ sbb r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ sbb r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ sbb r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ sbb r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ sbb r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ sbb r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ sbb r10, QWORD PTR [r8+248]
+ mov QWORD PTR [rcx+248], r10
+ sbb rax, 0
+ ret
+sp_2048_sub_32 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 2048 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_mont_reduce_avx2_32 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 32
+ mov r11, 32
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 128
+ xor rbp, rbp
+L_2048_mont_loop_avx2_32:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-96]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-88]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-88], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-80], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+-64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-72], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+-56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-64], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+-48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-56], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+-40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-48], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+-32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-40], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+-24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-32], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+16] += m[16] * mu
+ mulx rcx, rax, QWORD PTR [r10+128]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+17] += m[17] * mu
+ mulx rcx, rax, QWORD PTR [r10+136]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+18] += m[18] * mu
+ mulx rcx, rax, QWORD PTR [r10+144]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+19] += m[19] * mu
+ mulx rcx, rax, QWORD PTR [r10+152]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+20] += m[20] * mu
+ mulx rcx, rax, QWORD PTR [r10+160]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+21] += m[21] * mu
+ mulx rcx, rax, QWORD PTR [r10+168]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+22] += m[22] * mu
+ mulx rcx, rax, QWORD PTR [r10+176]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+23] += m[23] * mu
+ mulx rcx, rax, QWORD PTR [r10+184]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ ; a[i+24] += m[24] * mu
+ mulx rcx, rax, QWORD PTR [r10+192]
+ mov r13, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+64], r12
+ ; a[i+25] += m[25] * mu
+ mulx rcx, rax, QWORD PTR [r10+200]
+ mov r12, QWORD PTR [r9+80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+72], r13
+ ; a[i+26] += m[26] * mu
+ mulx rcx, rax, QWORD PTR [r10+208]
+ mov r13, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+80], r12
+ ; a[i+27] += m[27] * mu
+ mulx rcx, rax, QWORD PTR [r10+216]
+ mov r12, QWORD PTR [r9+96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+88], r13
+ ; a[i+28] += m[28] * mu
+ mulx rcx, rax, QWORD PTR [r10+224]
+ mov r13, QWORD PTR [r9+104]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+96], r12
+ ; a[i+29] += m[29] * mu
+ mulx rcx, rax, QWORD PTR [r10+232]
+ mov r12, QWORD PTR [r9+112]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+104], r13
+ ; a[i+30] += m[30] * mu
+ mulx rcx, rax, QWORD PTR [r10+240]
+ mov r13, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+112], r12
+ ; a[i+31] += m[31] * mu
+ mulx rcx, rax, QWORD PTR [r10+248]
+ mov r12, QWORD PTR [r9+128]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+120], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+128], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 1
+ add r9, 8
+ ; i -= 1
+ sub r11, 1
+ jnz L_2048_mont_loop_avx2_32
+ sub r9, 128
+ neg rbp
+ mov r8, r9
+ sub r9, 256
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+128]
+ mov rax, QWORD PTR [r8+128]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+120], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+136]
+ mov rcx, QWORD PTR [r8+136]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+128], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+144]
+ mov rdx, QWORD PTR [r8+144]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+136], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r8+152]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+144], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+160]
+ mov rcx, QWORD PTR [r8+160]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+152], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+168]
+ mov rdx, QWORD PTR [r8+168]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+160], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+176]
+ mov rax, QWORD PTR [r8+176]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+168], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+184]
+ mov rcx, QWORD PTR [r8+184]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+176], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+192]
+ mov rdx, QWORD PTR [r8+192]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+184], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [r8+200]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+192], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+208]
+ mov rcx, QWORD PTR [r8+208]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+200], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+216]
+ mov rdx, QWORD PTR [r8+216]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+208], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+224]
+ mov rax, QWORD PTR [r8+224]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+216], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+232]
+ mov rcx, QWORD PTR [r8+232]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+224], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+240]
+ mov rdx, QWORD PTR [r8+240]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+232], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [r8+248]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+240], rdx
+ sbb rax, rcx
+ mov QWORD PTR [r9+248], rax
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_2048_mont_reduce_avx2_32 ENDP
+_text ENDS
+ENDIF
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_add_16 PROC
+ sub rsp, 128
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ add r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ adc r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ adc r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ adc r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ adc r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ adc r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ adc r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ adc r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ adc r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ adc r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ adc r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ adc r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ adc r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ adc r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ adc r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ adc r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ adc rax, 0
+ add rsp, 128
+ ret
+sp_2048_cond_add_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_cond_add_avx2_16 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ add r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ adc r10, r11
+ mov QWORD PTR [rcx+120], r10
+ adc rax, 0
+ pop r12
+ ret
+sp_2048_cond_add_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Shift number left by n bit. (r = a << n)
+; *
+; * r Result of left shift by n.
+; * a Number to shift.
+; * n Amoutnt o shift.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_lshift_32 PROC
+ push r12
+ push r13
+ mov r9, rcx
+ mov rcx, r8
+ mov r12, 0
+ mov r13, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rdx+232]
+ mov r10, QWORD PTR [rdx+240]
+ mov r11, QWORD PTR [rdx+248]
+ shld r12, r11, cl
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+224], rax
+ mov QWORD PTR [r9+232], r8
+ mov QWORD PTR [r9+240], r10
+ mov QWORD PTR [r9+248], r11
+ mov QWORD PTR [r9+256], r12
+ mov r11, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rdx+200]
+ mov r10, QWORD PTR [rdx+208]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+192], rax
+ mov QWORD PTR [r9+200], r8
+ mov QWORD PTR [r9+208], r10
+ mov QWORD PTR [r9+216], r13
+ mov r13, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov r10, QWORD PTR [rdx+176]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+160], rax
+ mov QWORD PTR [r9+168], r8
+ mov QWORD PTR [r9+176], r10
+ mov QWORD PTR [r9+184], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov r10, QWORD PTR [rdx+144]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+128], rax
+ mov QWORD PTR [r9+136], r8
+ mov QWORD PTR [r9+144], r10
+ mov QWORD PTR [r9+152], r13
+ mov r13, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+96], rax
+ mov QWORD PTR [r9+104], r8
+ mov QWORD PTR [r9+112], r10
+ mov QWORD PTR [r9+120], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+64], rax
+ mov QWORD PTR [r9+72], r8
+ mov QWORD PTR [r9+80], r10
+ mov QWORD PTR [r9+88], r13
+ mov r13, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+32], rax
+ mov QWORD PTR [r9+40], r8
+ mov QWORD PTR [r9+48], r10
+ mov QWORD PTR [r9+56], r11
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shl rax, cl
+ mov QWORD PTR [r9], rax
+ mov QWORD PTR [r9+8], r8
+ mov QWORD PTR [r9+16], r10
+ mov QWORD PTR [r9+24], r13
+ pop r13
+ pop r12
+ ret
+sp_2048_lshift_32 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFNDEF WOLFSSL_SP_NO_3072
+IFNDEF WOLFSSL_SP_NO_3072
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 384
+ xor r13, r13
+ jmp L_3072_from_bin_bswap_64_end
+L_3072_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_3072_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_3072_from_bin_bswap_64_start
+ jmp L_3072_from_bin_bswap_8_end
+L_3072_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_3072_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_3072_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_3072_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_3072_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_3072_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_3072_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_3072_from_bin_bswap_zero_end
+L_3072_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_3072_from_bin_bswap_zero_start
+L_3072_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_3072_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 384
+ xor r13, r13
+ jmp L_3072_from_bin_movbe_64_end
+L_3072_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_3072_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_3072_from_bin_movbe_64_start
+ jmp L_3072_from_bin_movbe_8_end
+L_3072_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_3072_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_3072_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_3072_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_3072_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_3072_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_3072_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_3072_from_bin_movbe_zero_end
+L_3072_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_3072_from_bin_movbe_zero_start
+L_3072_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_3072_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 384
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_to_bin_bswap PROC
+ mov rax, QWORD PTR [rcx+376]
+ mov r8, QWORD PTR [rcx+368]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ mov rax, QWORD PTR [rcx+360]
+ mov r8, QWORD PTR [rcx+352]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ mov rax, QWORD PTR [rcx+344]
+ mov r8, QWORD PTR [rcx+336]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ mov rax, QWORD PTR [rcx+328]
+ mov r8, QWORD PTR [rcx+320]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ mov rax, QWORD PTR [rcx+312]
+ mov r8, QWORD PTR [rcx+304]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ mov rax, QWORD PTR [rcx+296]
+ mov r8, QWORD PTR [rcx+288]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ mov rax, QWORD PTR [rcx+280]
+ mov r8, QWORD PTR [rcx+272]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ mov rax, QWORD PTR [rcx+264]
+ mov r8, QWORD PTR [rcx+256]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ mov rax, QWORD PTR [rcx+248]
+ mov r8, QWORD PTR [rcx+240]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ mov rax, QWORD PTR [rcx+232]
+ mov r8, QWORD PTR [rcx+224]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ mov rax, QWORD PTR [rcx+216]
+ mov r8, QWORD PTR [rcx+208]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ mov rax, QWORD PTR [rcx+200]
+ mov r8, QWORD PTR [rcx+192]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ mov rax, QWORD PTR [rcx+184]
+ mov r8, QWORD PTR [rcx+176]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ mov rax, QWORD PTR [rcx+168]
+ mov r8, QWORD PTR [rcx+160]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ mov rax, QWORD PTR [rcx+152]
+ mov r8, QWORD PTR [rcx+144]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ mov rax, QWORD PTR [rcx+136]
+ mov r8, QWORD PTR [rcx+128]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ mov rax, QWORD PTR [rcx+120]
+ mov r8, QWORD PTR [rcx+112]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+256], rax
+ mov QWORD PTR [rdx+264], r8
+ mov rax, QWORD PTR [rcx+104]
+ mov r8, QWORD PTR [rcx+96]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+272], rax
+ mov QWORD PTR [rdx+280], r8
+ mov rax, QWORD PTR [rcx+88]
+ mov r8, QWORD PTR [rcx+80]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+288], rax
+ mov QWORD PTR [rdx+296], r8
+ mov rax, QWORD PTR [rcx+72]
+ mov r8, QWORD PTR [rcx+64]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+304], rax
+ mov QWORD PTR [rdx+312], r8
+ mov rax, QWORD PTR [rcx+56]
+ mov r8, QWORD PTR [rcx+48]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+320], rax
+ mov QWORD PTR [rdx+328], r8
+ mov rax, QWORD PTR [rcx+40]
+ mov r8, QWORD PTR [rcx+32]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+336], rax
+ mov QWORD PTR [rdx+344], r8
+ mov rax, QWORD PTR [rcx+24]
+ mov r8, QWORD PTR [rcx+16]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+352], rax
+ mov QWORD PTR [rdx+360], r8
+ mov rax, QWORD PTR [rcx+8]
+ mov r8, QWORD PTR [rcx]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+368], rax
+ mov QWORD PTR [rdx+376], r8
+ ret
+sp_3072_to_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 384
+; * Uses the movbe instruction which is optional.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_to_bin_movbe PROC
+ movbe rax, QWORD PTR [rcx+376]
+ movbe r8, QWORD PTR [rcx+368]
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ movbe rax, QWORD PTR [rcx+360]
+ movbe r8, QWORD PTR [rcx+352]
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ movbe rax, QWORD PTR [rcx+344]
+ movbe r8, QWORD PTR [rcx+336]
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ movbe rax, QWORD PTR [rcx+328]
+ movbe r8, QWORD PTR [rcx+320]
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ movbe rax, QWORD PTR [rcx+312]
+ movbe r8, QWORD PTR [rcx+304]
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ movbe rax, QWORD PTR [rcx+296]
+ movbe r8, QWORD PTR [rcx+288]
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ movbe rax, QWORD PTR [rcx+280]
+ movbe r8, QWORD PTR [rcx+272]
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ movbe rax, QWORD PTR [rcx+264]
+ movbe r8, QWORD PTR [rcx+256]
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ movbe rax, QWORD PTR [rcx+248]
+ movbe r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ movbe rax, QWORD PTR [rcx+232]
+ movbe r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ movbe rax, QWORD PTR [rcx+216]
+ movbe r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ movbe rax, QWORD PTR [rcx+200]
+ movbe r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ movbe rax, QWORD PTR [rcx+184]
+ movbe r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ movbe rax, QWORD PTR [rcx+168]
+ movbe r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ movbe rax, QWORD PTR [rcx+152]
+ movbe r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ movbe rax, QWORD PTR [rcx+136]
+ movbe r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ movbe rax, QWORD PTR [rcx+120]
+ movbe r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rdx+256], rax
+ mov QWORD PTR [rdx+264], r8
+ movbe rax, QWORD PTR [rcx+104]
+ movbe r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rdx+272], rax
+ mov QWORD PTR [rdx+280], r8
+ movbe rax, QWORD PTR [rcx+88]
+ movbe r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rdx+288], rax
+ mov QWORD PTR [rdx+296], r8
+ movbe rax, QWORD PTR [rcx+72]
+ movbe r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rdx+304], rax
+ mov QWORD PTR [rdx+312], r8
+ movbe rax, QWORD PTR [rcx+56]
+ movbe r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rdx+320], rax
+ mov QWORD PTR [rdx+328], r8
+ movbe rax, QWORD PTR [rcx+40]
+ movbe r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rdx+336], rax
+ mov QWORD PTR [rdx+344], r8
+ movbe rax, QWORD PTR [rcx+24]
+ movbe r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rdx+352], rax
+ mov QWORD PTR [rdx+360], r8
+ movbe rax, QWORD PTR [rcx+8]
+ movbe r8, QWORD PTR [rcx]
+ mov QWORD PTR [rdx+368], rax
+ mov QWORD PTR [rdx+376], r8
+ ret
+sp_3072_to_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_12 PROC
+ push r12
+ mov r9, rdx
+ sub rsp, 96
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ mov QWORD PTR [rsp], rax
+ mov r11, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+8], r11
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+16], r12
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+24], r10
+ ; A[0] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+32], r11
+ ; A[0] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+40], r12
+ ; A[0] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+48], r10
+ ; A[0] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+56], r11
+ ; A[0] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+64], r12
+ ; A[0] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+72], r10
+ ; A[0] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+80], r11
+ ; A[0] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+88], r12
+ ; A[1] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+8]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+96], r10
+ ; A[2] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+16]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+104], r11
+ ; A[3] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+24]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+112], r12
+ ; A[4] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+32]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+120], r10
+ ; A[5] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+40]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+128], r11
+ ; A[6] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+48]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+136], r12
+ ; A[7] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+56]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+144], r10
+ ; A[8] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+64]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+152], r11
+ ; A[9] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+72]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+160], r12
+ ; A[10] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+80]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+168], r10
+ ; A[11] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ mov QWORD PTR [rcx+176], r11
+ mov QWORD PTR [rcx+184], r12
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r10, QWORD PTR [rsp+16]
+ mov r11, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r10, QWORD PTR [rsp+48]
+ mov r11, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r10, QWORD PTR [rsp+80]
+ mov r11, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ add rsp, 96
+ pop r12
+ ret
+sp_3072_mul_12 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_12 PROC
+ push r12
+ push r13
+ push r14
+ mov r8, rdx
+ sub rsp, 96
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ xor r11, r11
+ mov QWORD PTR [rsp], rax
+ mov r10, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+8], r10
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+16], r11
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+8]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+24], r9
+ ; A[0] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+8]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+32], r10
+ ; A[0] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+40], r11
+ ; A[0] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+48], r9
+ ; A[0] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+56], r10
+ ; A[0] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+64], r11
+ ; A[0] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+72], r9
+ ; A[0] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+80], r10
+ ; A[0] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+88], r11
+ ; A[1] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[2] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+96], r9
+ ; A[2] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+16]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[3] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+104], r10
+ ; A[3] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+24]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[4] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+112], r11
+ ; A[4] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+32]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[5] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+120], r9
+ ; A[5] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+40]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[6] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+128], r10
+ ; A[6] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+48]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[7] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+136], r11
+ ; A[7] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+56]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+64]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul rax
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+144], r9
+ ; A[8] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+64]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[9] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+72]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rcx+152], r10
+ ; A[9] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+72]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[10] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+160], r11
+ ; A[10] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+80]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+168], r9
+ ; A[11] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+176], r10
+ mov QWORD PTR [rcx+184], r11
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r12, QWORD PTR [rsp+16]
+ mov r13, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r12, QWORD PTR [rsp+48]
+ mov r13, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r12
+ mov QWORD PTR [rcx+56], r13
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r12, QWORD PTR [rsp+80]
+ mov r13, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r12
+ mov QWORD PTR [rcx+88], r13
+ add rsp, 96
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_sqr_12 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r Result of multiplication.
+; * a First number to multiply.
+; * b Second number to multiply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_avx2_12 PROC
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ mov rbp, r8
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 96
+ cmp r9, r8
+ mov rbx, rsp
+ cmovne rbx, r8
+ cmp rbp, r8
+ cmove rbx, rsp
+ add r8, 96
+ xor r14, r14
+ mov rdx, QWORD PTR [r9]
+ ; A[0] * B[0]
+ mulx r11, r10, QWORD PTR [rbp]
+ ; A[0] * B[1]
+ mulx r12, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx], r10
+ adcx r11, rax
+ mov QWORD PTR [rbx+8], r11
+ ; A[0] * B[2]
+ mulx r10, rax, QWORD PTR [rbp+16]
+ adcx r12, rax
+ ; A[0] * B[3]
+ mulx r11, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+16], r12
+ adcx r10, rax
+ mov QWORD PTR [rbx+24], r10
+ ; A[0] * B[4]
+ mulx r12, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ ; A[0] * B[5]
+ mulx r10, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+32], r11
+ adcx r12, rax
+ mov QWORD PTR [rbx+40], r12
+ ; A[0] * B[6]
+ mulx r11, rax, QWORD PTR [rbp+48]
+ adcx r10, rax
+ ; A[0] * B[7]
+ mulx r12, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+48], r10
+ adcx r11, rax
+ mov QWORD PTR [rbx+56], r11
+ ; A[0] * B[8]
+ mulx r10, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ ; A[0] * B[9]
+ mulx r11, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+64], r12
+ adcx r10, rax
+ mov QWORD PTR [rbx+72], r10
+ ; A[0] * B[10]
+ mulx r12, rax, QWORD PTR [rbp+80]
+ adcx r11, rax
+ ; A[0] * B[11]
+ mulx r10, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adcx r10, r14
+ mov r13, r14
+ adcx r13, r14
+ mov QWORD PTR [rbx+88], r12
+ mov QWORD PTR [r8], r10
+ mov rdx, QWORD PTR [r9+8]
+ mov r11, QWORD PTR [rbx+8]
+ mov r12, QWORD PTR [rbx+16]
+ mov r10, QWORD PTR [rbx+24]
+ ; A[1] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+8], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+16], r12
+ mov r11, QWORD PTR [rbx+32]
+ mov r12, QWORD PTR [rbx+40]
+ ; A[1] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+24], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+32], r11
+ mov r10, QWORD PTR [rbx+48]
+ mov r11, QWORD PTR [rbx+56]
+ ; A[1] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[1] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+40], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+48], r10
+ mov r12, QWORD PTR [rbx+64]
+ mov r10, QWORD PTR [rbx+72]
+ ; A[1] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+56], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+64], r12
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ ; A[1] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+80], r11
+ mov r10, QWORD PTR [r8]
+ ; A[1] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[1] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+88], r12
+ mov r11, r14
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8], r10
+ mov QWORD PTR [r8+8], r11
+ mov rdx, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [rbx+16]
+ mov r10, QWORD PTR [rbx+24]
+ mov r11, QWORD PTR [rbx+32]
+ ; A[2] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[2] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+16], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+24], r10
+ mov r12, QWORD PTR [rbx+40]
+ mov r10, QWORD PTR [rbx+48]
+ ; A[2] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+32], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+40], r12
+ mov r11, QWORD PTR [rbx+56]
+ mov r12, QWORD PTR [rbx+64]
+ ; A[2] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+48], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+56], r11
+ mov r10, QWORD PTR [rbx+72]
+ mov r11, QWORD PTR [rbx+80]
+ ; A[2] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[2] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+64], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+72], r10
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ ; A[2] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+88], r12
+ mov r11, QWORD PTR [r8+8]
+ ; A[2] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8], r10
+ mov r12, r14
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+8], r11
+ mov QWORD PTR [r8+16], r12
+ mov rdx, QWORD PTR [r9+24]
+ mov r10, QWORD PTR [rbx+24]
+ mov r11, QWORD PTR [rbx+32]
+ mov r12, QWORD PTR [rbx+40]
+ ; A[3] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+24], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+32], r11
+ mov r10, QWORD PTR [rbx+48]
+ mov r11, QWORD PTR [rbx+56]
+ ; A[3] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[3] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+40], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+48], r10
+ mov r12, QWORD PTR [rbx+64]
+ mov r10, QWORD PTR [rbx+72]
+ ; A[3] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+56], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+64], r12
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ ; A[3] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+80], r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[3] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[3] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+88], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ ; A[3] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+8], r11
+ mov r10, r14
+ adcx r12, rax
+ adox r10, rcx
+ adcx r10, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+16], r12
+ mov QWORD PTR [r8+24], r10
+ mov rdx, QWORD PTR [r9+32]
+ mov r11, QWORD PTR [rbx+32]
+ mov r12, QWORD PTR [rbx+40]
+ mov r10, QWORD PTR [rbx+48]
+ ; A[4] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+32], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+40], r12
+ mov r11, QWORD PTR [rbx+56]
+ mov r12, QWORD PTR [rbx+64]
+ ; A[4] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+48], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+56], r11
+ mov r10, QWORD PTR [rbx+72]
+ mov r11, QWORD PTR [rbx+80]
+ ; A[4] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[4] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+64], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+72], r10
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ ; A[4] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+88], r12
+ mov r11, QWORD PTR [r8+8]
+ mov r12, QWORD PTR [r8+16]
+ ; A[4] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+24]
+ ; A[4] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[4] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+16], r12
+ mov r11, r14
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+24], r10
+ mov QWORD PTR [r8+32], r11
+ mov rdx, QWORD PTR [r9+40]
+ mov r12, QWORD PTR [rbx+40]
+ mov r10, QWORD PTR [rbx+48]
+ mov r11, QWORD PTR [rbx+56]
+ ; A[5] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[5] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+40], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+48], r10
+ mov r12, QWORD PTR [rbx+64]
+ mov r10, QWORD PTR [rbx+72]
+ ; A[5] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+56], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+64], r12
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ ; A[5] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+80], r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[5] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[5] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+88], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[5] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+8], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ ; A[5] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+24], r10
+ mov r12, r14
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+32], r11
+ mov QWORD PTR [r8+40], r12
+ mov rdx, QWORD PTR [r9+48]
+ mov r10, QWORD PTR [rbx+48]
+ mov r11, QWORD PTR [rbx+56]
+ mov r12, QWORD PTR [rbx+64]
+ ; A[6] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+48], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+56], r11
+ mov r10, QWORD PTR [rbx+72]
+ mov r11, QWORD PTR [rbx+80]
+ ; A[6] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[6] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+64], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+72], r10
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ ; A[6] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+88], r12
+ mov r11, QWORD PTR [r8+8]
+ mov r12, QWORD PTR [r8+16]
+ ; A[6] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+24]
+ mov r11, QWORD PTR [r8+32]
+ ; A[6] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[6] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+16], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r10
+ mov r12, QWORD PTR [r8+40]
+ ; A[6] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+32], r11
+ mov r10, r14
+ adcx r12, rax
+ adox r10, rcx
+ adcx r10, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+40], r12
+ mov QWORD PTR [r8+48], r10
+ mov rdx, QWORD PTR [r9+56]
+ mov r11, QWORD PTR [rbx+56]
+ mov r12, QWORD PTR [rbx+64]
+ mov r10, QWORD PTR [rbx+72]
+ ; A[7] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+56], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+64], r12
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ ; A[7] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+80], r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[7] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[7] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+88], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[7] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+8], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, QWORD PTR [r8+40]
+ ; A[7] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+24], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+32], r11
+ mov r10, QWORD PTR [r8+48]
+ ; A[7] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[7] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+40], r12
+ mov r11, r14
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+48], r10
+ mov QWORD PTR [r8+56], r11
+ mov rdx, QWORD PTR [r9+64]
+ mov r12, QWORD PTR [rbx+64]
+ mov r10, QWORD PTR [rbx+72]
+ mov r11, QWORD PTR [rbx+80]
+ ; A[8] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[8] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+64], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+72], r10
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ ; A[8] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+88], r12
+ mov r11, QWORD PTR [r8+8]
+ mov r12, QWORD PTR [r8+16]
+ ; A[8] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+24]
+ mov r11, QWORD PTR [r8+32]
+ ; A[8] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[8] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+16], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r10
+ mov r12, QWORD PTR [r8+40]
+ mov r10, QWORD PTR [r8+48]
+ ; A[8] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+32], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r12
+ mov r11, QWORD PTR [r8+56]
+ ; A[8] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+48], r10
+ mov r12, r14
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+56], r11
+ mov QWORD PTR [r8+64], r12
+ mov rdx, QWORD PTR [r9+72]
+ mov r10, QWORD PTR [rbx+72]
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ ; A[9] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+80], r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[9] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[9] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+88], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[9] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+8], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, QWORD PTR [r8+40]
+ ; A[9] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+24], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+32], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[9] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[9] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+40], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov r12, QWORD PTR [r8+64]
+ ; A[9] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+56], r11
+ mov r10, r14
+ adcx r12, rax
+ adox r10, rcx
+ adcx r10, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+64], r12
+ mov QWORD PTR [r8+72], r10
+ mov rdx, QWORD PTR [r9+80]
+ mov r11, QWORD PTR [rbx+80]
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ ; A[10] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+80], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+88], r12
+ mov r11, QWORD PTR [r8+8]
+ mov r12, QWORD PTR [r8+16]
+ ; A[10] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+24]
+ mov r11, QWORD PTR [r8+32]
+ ; A[10] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[10] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+16], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r10
+ mov r12, QWORD PTR [r8+40]
+ mov r10, QWORD PTR [r8+48]
+ ; A[10] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+32], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r12
+ mov r11, QWORD PTR [r8+56]
+ mov r12, QWORD PTR [r8+64]
+ ; A[10] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+48], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+56], r11
+ mov r10, QWORD PTR [r8+72]
+ ; A[10] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[10] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+64], r12
+ mov r11, r14
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r13
+ mov r13, r14
+ adox r13, r14
+ adcx r13, r14
+ mov QWORD PTR [r8+72], r10
+ mov QWORD PTR [r8+80], r11
+ mov rdx, QWORD PTR [r9+88]
+ mov r12, QWORD PTR [rbx+88]
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[11] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[11] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+88], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[11] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8+8], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, QWORD PTR [r8+40]
+ ; A[11] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+24], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+32], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[11] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[11] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+40], r12
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov r12, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[11] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+56], r11
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+64], r12
+ mov r11, QWORD PTR [r8+80]
+ ; A[11] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+72], r10
+ mov r12, r14
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r13
+ mov QWORD PTR [r8+80], r11
+ mov QWORD PTR [r8+88], r12
+ sub r8, 96
+ cmp r9, r8
+ je L_start_3072_mul_avx2_12
+ cmp rbp, r8
+ jne L_end_3072_mul_avx2_12
+L_start_3072_mul_avx2_12:
+ vmovdqu xmm0, OWORD PTR [rbx]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+48]
+ vmovups OWORD PTR [r8+48], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+64]
+ vmovups OWORD PTR [r8+64], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+80]
+ vmovups OWORD PTR [r8+80], xmm0
+L_end_3072_mul_avx2_12:
+ add rsp, 96
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ pop rbx
+ ret
+sp_3072_mul_avx2_12 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_avx2_12 PROC
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 96
+ cmp r9, r8
+ mov rbp, rsp
+ cmovne rbp, r8
+ add r8, 96
+ xor r12, r12
+ ; Diagonal 1
+ ; A[1] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx r11, r10, QWORD PTR [r9+8]
+ mov QWORD PTR [rbp+8], r10
+ mov r10, r12
+ ; A[2] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+16], r11
+ mov r11, r12
+ ; A[3] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+24], r10
+ mov r10, r12
+ ; A[4] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+32], r11
+ mov r11, r12
+ ; A[5] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+40], r10
+ mov r10, r12
+ ; A[6] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+48], r11
+ mov r11, r12
+ ; A[7] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov r14, r10
+ mov r10, r12
+ ; A[8] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r10, rcx
+ mov r15, r11
+ mov r11, r12
+ ; A[9] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov rdi, r10
+ mov r10, r12
+ ; A[10] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r10, rcx
+ mov rsi, r11
+ mov r11, r12
+ ; A[11] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r10, rax
+ adox r11, rcx
+ mov rbx, r10
+ ; Carry
+ adcx r11, r12
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8], r11
+ ; Diagonal 2
+ mov r11, QWORD PTR [rbp+24]
+ mov r10, QWORD PTR [rbp+32]
+ ; A[2] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+24], r11
+ mov r11, QWORD PTR [rbp+40]
+ ; A[3] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+32], r10
+ mov r10, QWORD PTR [rbp+48]
+ ; A[4] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+40], r11
+ ; No load %r12 - %r9
+ ; A[5] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r14, rcx
+ mov QWORD PTR [rbp+48], r10
+ ; No load %r13 - %r8
+ ; A[6] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r14, rax
+ adox r15, rcx
+ ; No store %r12
+ ; No load %r14 - %r9
+ ; A[7] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r15, rax
+ adox rdi, rcx
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; A[8] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; No store %r14
+ ; No load %rbx - %r9
+ ; A[9] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ ; A[10] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rbx, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov r11, r12
+ ; A[11] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r10, r12
+ ; A[11] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ ; Carry
+ adcx r10, r13
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8+16], r10
+ ; Diagonal 3
+ mov r10, QWORD PTR [rbp+40]
+ mov r11, QWORD PTR [rbp+48]
+ ; A[3] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+40], r10
+ ; No load %r12 - %r8
+ ; A[4] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r14, rcx
+ mov QWORD PTR [rbp+48], r11
+ ; No load %r13 - %r9
+ ; A[5] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r14, rax
+ adox r15, rcx
+ ; No store %r12
+ ; No load %r14 - %r8
+ ; A[6] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r15, rax
+ adox rdi, rcx
+ ; No store %r13
+ ; No load %r15 - %r9
+ ; A[7] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; No store %r14
+ ; No load %rbx - %r8
+ ; A[8] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ ; A[9] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rbx, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov r10, QWORD PTR [r8+8]
+ ; A[10] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8], r11
+ mov r11, QWORD PTR [r8+16]
+ ; A[10] x A[3]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r10
+ mov r10, r12
+ ; A[10] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r11
+ mov r11, r12
+ ; A[10] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r10
+ ; Carry
+ adcx r11, r13
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8+32], r11
+ ; Diagonal 4
+ ; No load %r12 - %r9
+ ; No load %r13 - %r8
+ ; A[4] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r14, rax
+ adox r15, rcx
+ ; No store %r12
+ ; No load %r14 - %r9
+ ; A[5] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r15, rax
+ adox rdi, rcx
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; A[6] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; No store %r14
+ ; No load %rbx - %r9
+ ; A[7] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ ; A[8] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rbx, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov r11, QWORD PTR [r8+8]
+ ; A[9] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r10, QWORD PTR [r8+16]
+ ; A[9] x A[4]
+ mov rdx, QWORD PTR [r9+72]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r11, QWORD PTR [r8+24]
+ ; A[9] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+16], r10
+ mov r10, QWORD PTR [r8+32]
+ ; A[9] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov r11, r12
+ ; A[9] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r10, r12
+ ; A[9] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r11
+ ; Carry
+ adcx r10, r13
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8+48], r10
+ ; Diagonal 5
+ ; No load %r14 - %r8
+ ; No load %r15 - %r9
+ ; A[5] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; No store %r14
+ ; No load %rbx - %r8
+ ; A[6] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ ; A[7] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx rbx, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov r10, QWORD PTR [r8+8]
+ ; A[8] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8], r11
+ mov r11, QWORD PTR [r8+16]
+ ; A[8] x A[5]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r10
+ mov r10, QWORD PTR [r8+24]
+ ; A[8] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+16], r11
+ mov r11, QWORD PTR [r8+32]
+ ; A[8] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r10
+ mov r10, QWORD PTR [r8+40]
+ ; A[10] x A[6]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+32], r11
+ mov r11, QWORD PTR [r8+48]
+ ; A[10] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+40], r10
+ mov r10, r12
+ ; A[10] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+48], r11
+ mov r11, r12
+ ; A[10] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+56], r10
+ ; Carry
+ adcx r11, r13
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8+64], r11
+ ; Diagonal 6
+ ; No load %rbx - %r9
+ mov r10, QWORD PTR [r8]
+ ; A[6] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx rbx, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov r11, QWORD PTR [r8+8]
+ ; A[7] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8], r10
+ mov r10, QWORD PTR [r8+16]
+ ; A[7] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov r11, QWORD PTR [r8+24]
+ ; A[11] x A[3]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+16], r10
+ mov r10, QWORD PTR [r8+32]
+ ; A[11] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov r11, QWORD PTR [r8+40]
+ ; A[11] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r10, QWORD PTR [r8+48]
+ ; A[11] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r11
+ mov r11, QWORD PTR [r8+56]
+ ; A[11] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov r10, QWORD PTR [r8+64]
+ ; A[11] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+56], r11
+ mov r11, r12
+ ; A[11] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+64], r10
+ mov r10, r12
+ ; A[11] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+72], r11
+ ; Carry
+ adcx r10, r13
+ mov r13, r12
+ adcx r13, r12
+ adox r13, r12
+ mov QWORD PTR [r8+80], r10
+ mov QWORD PTR [r8+88], r13
+ ; Double and Add in A[i] x A[i]
+ mov r11, QWORD PTR [rbp+8]
+ ; A[0] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx rcx, rax, rdx
+ mov QWORD PTR [rbp], rax
+ adox r11, r11
+ adcx r11, rcx
+ mov QWORD PTR [rbp+8], r11
+ mov r10, QWORD PTR [rbp+16]
+ mov r11, QWORD PTR [rbp+24]
+ ; A[1] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+16], r10
+ mov QWORD PTR [rbp+24], r11
+ mov r10, QWORD PTR [rbp+32]
+ mov r11, QWORD PTR [rbp+40]
+ ; A[2] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+32], r10
+ mov QWORD PTR [rbp+40], r11
+ mov r10, QWORD PTR [rbp+48]
+ ; A[3] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r14, r14
+ adcx r10, rax
+ adcx r14, rcx
+ mov QWORD PTR [rbp+48], r10
+ ; A[4] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, rdx
+ adox r15, r15
+ adox rdi, rdi
+ adcx r15, rax
+ adcx rdi, rcx
+ ; A[5] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, rdx
+ adox rsi, rsi
+ adox rbx, rbx
+ adcx rsi, rax
+ adcx rbx, rcx
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[6] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8], r10
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[7] x A[7]
+ mov rdx, QWORD PTR [r9+56]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+16], r10
+ mov QWORD PTR [r8+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[8] x A[8]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov QWORD PTR [r8+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[9] x A[9]
+ mov rdx, QWORD PTR [r9+72]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov QWORD PTR [r8+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ ; A[10] x A[10]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+64], r10
+ mov QWORD PTR [r8+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ ; A[11] x A[11]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+80], r10
+ mov QWORD PTR [r8+88], r11
+ mov QWORD PTR [r8+-40], r14
+ mov QWORD PTR [r8+-32], r15
+ mov QWORD PTR [r8+-24], rdi
+ mov QWORD PTR [r8+-16], rsi
+ mov QWORD PTR [r8+-8], rbx
+ sub r8, 96
+ cmp r9, r8
+ jne L_end_3072_sqr_avx2_12
+ vmovdqu xmm0, OWORD PTR [rbp]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ mov rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+48], rax
+L_end_3072_sqr_avx2_12:
+ add rsp, 96
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ ret
+sp_3072_sqr_avx2_12 ENDP
+_text ENDS
+ENDIF
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_add_12 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov QWORD PTR [rcx+88], r10
+ adc rax, 0
+ ret
+sp_3072_add_12 ENDP
+_text ENDS
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sub_in_place_24 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rcx+120], r9
+ sbb r8, QWORD PTR [rdx+128]
+ mov r9, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], r8
+ sbb r9, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r9
+ sbb r8, QWORD PTR [rdx+144]
+ mov r9, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], r8
+ sbb r9, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r9
+ sbb r8, QWORD PTR [rdx+160]
+ mov r9, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], r8
+ sbb r9, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r9
+ sbb r8, QWORD PTR [rdx+176]
+ mov r9, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], r8
+ sbb r9, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+184], r9
+ sbb rax, 0
+ ret
+sp_3072_sub_in_place_24 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_add_24 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ adc r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ adc r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ adc r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ adc r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ adc r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ adc r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ adc r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ adc r10, QWORD PTR [r8+184]
+ mov QWORD PTR [rcx+184], r10
+ adc rax, 0
+ ret
+sp_3072_add_24 ENDP
+_text ENDS
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_24 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 616
+ mov QWORD PTR [rsp+576], rcx
+ mov QWORD PTR [rsp+584], rdx
+ mov QWORD PTR [rsp+592], r8
+ lea r12, QWORD PTR [rsp+384]
+ lea r14, QWORD PTR [rdx+96]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov QWORD PTR [r12+88], r10
+ adc r15, 0
+ mov QWORD PTR [rsp+600], r15
+ lea r13, QWORD PTR [rsp+480]
+ lea r14, QWORD PTR [r8+96]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov QWORD PTR [r13+88], r10
+ adc rdi, 0
+ mov QWORD PTR [rsp+608], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_3072_mul_12
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ lea rcx, QWORD PTR [rsp+192]
+ add r8, 96
+ add rdx, 96
+ call sp_3072_mul_12
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ mov rcx, QWORD PTR [rsp+576]
+ call sp_3072_mul_12
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ mov rcx, QWORD PTR [rsp+576]
+ENDIF
+ mov r15, QWORD PTR [rsp+600]
+ mov rdi, QWORD PTR [rsp+608]
+ mov rsi, QWORD PTR [rsp+576]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+384]
+ lea r13, QWORD PTR [rsp+480]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 192
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12], rax
+ mov QWORD PTR [r13], r9
+ mov rax, QWORD PTR [r12+8]
+ mov r9, QWORD PTR [r13+8]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+8], rax
+ mov QWORD PTR [r13+8], r9
+ mov rax, QWORD PTR [r12+16]
+ mov r9, QWORD PTR [r13+16]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+16], rax
+ mov QWORD PTR [r13+16], r9
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+24], rax
+ mov QWORD PTR [r13+24], r9
+ mov rax, QWORD PTR [r12+32]
+ mov r9, QWORD PTR [r13+32]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+32], rax
+ mov QWORD PTR [r13+32], r9
+ mov rax, QWORD PTR [r12+40]
+ mov r9, QWORD PTR [r13+40]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+40], rax
+ mov QWORD PTR [r13+40], r9
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+48], rax
+ mov QWORD PTR [r13+48], r9
+ mov rax, QWORD PTR [r12+56]
+ mov r9, QWORD PTR [r13+56]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+56], rax
+ mov QWORD PTR [r13+56], r9
+ mov rax, QWORD PTR [r12+64]
+ mov r9, QWORD PTR [r13+64]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+64], rax
+ mov QWORD PTR [r13+64], r9
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+72], rax
+ mov QWORD PTR [r13+72], r9
+ mov rax, QWORD PTR [r12+80]
+ mov r9, QWORD PTR [r13+80]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+80], rax
+ mov QWORD PTR [r13+80], r9
+ mov rax, QWORD PTR [r12+88]
+ mov r9, QWORD PTR [r13+88]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+88], rax
+ mov QWORD PTR [r13+88], r9
+ mov rax, QWORD PTR [r12]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov QWORD PTR [rsi+88], r10
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+192]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov QWORD PTR [r12+184], r10
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov QWORD PTR [r12+184], r10
+ sbb r11, 0
+ sub rsi, 96
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov QWORD PTR [rsi+184], r10
+ adc r11, 0
+ mov QWORD PTR [rcx+288], r11
+ add rsi, 96
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov QWORD PTR [rsi+96], rax
+ ; Add to zero
+ mov rax, QWORD PTR [r13+104]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+112]
+ mov QWORD PTR [rsi+104], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+120]
+ mov QWORD PTR [rsi+112], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+128]
+ mov QWORD PTR [rsi+120], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+136]
+ mov QWORD PTR [rsi+128], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+144]
+ mov QWORD PTR [rsi+136], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+152]
+ mov QWORD PTR [rsi+144], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+160]
+ mov QWORD PTR [rsi+152], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+168]
+ mov QWORD PTR [rsi+160], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+176]
+ mov QWORD PTR [rsi+168], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+184]
+ mov QWORD PTR [rsi+176], rax
+ adc r9, 0
+ mov QWORD PTR [rsi+184], r9
+ add rsp, 616
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_24 ENDP
+_text ENDS
+; /* Add a to a into r. (r = a + a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_dbl_12 PROC
+ mov r8, QWORD PTR [rdx]
+ xor rax, rax
+ add r8, r8
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r8
+ adc r9, r9
+ mov QWORD PTR [rcx+88], r9
+ adc rax, 0
+ ret
+sp_3072_dbl_12 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_24 PROC
+ push r12
+ sub rsp, 504
+ mov QWORD PTR [rsp+480], rcx
+ mov QWORD PTR [rsp+488], rdx
+ lea r10, QWORD PTR [rsp+384]
+ lea r11, QWORD PTR [rdx+96]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r10+88], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+496], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_3072_sqr_12
+ mov rdx, QWORD PTR [rsp+488]
+ lea rcx, QWORD PTR [rsp+192]
+ add rdx, 96
+ call sp_3072_sqr_12
+ mov rdx, QWORD PTR [rsp+488]
+ mov rcx, QWORD PTR [rsp+480]
+ call sp_3072_sqr_12
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+488]
+ mov rcx, QWORD PTR [rsp+480]
+ENDIF
+ mov r12, QWORD PTR [rsp+496]
+ mov r11, rcx
+ lea r10, QWORD PTR [rsp+384]
+ mov r9, r12
+ neg r12
+ add r11, 192
+ mov rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r10+8]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11], rax
+ mov QWORD PTR [r11+8], r8
+ mov rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r10+24]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+16], rax
+ mov QWORD PTR [r11+24], r8
+ mov rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r10+40]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+32], rax
+ mov QWORD PTR [r11+40], r8
+ mov rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r10+56]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+48], rax
+ mov QWORD PTR [r11+56], r8
+ mov rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r10+72]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+64], rax
+ mov QWORD PTR [r11+72], r8
+ mov rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r10+88]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+80], rax
+ mov QWORD PTR [r11+88], r8
+ mov rax, QWORD PTR [r11]
+ add rax, rax
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, r8
+ mov QWORD PTR [r11+88], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+192]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+184], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov QWORD PTR [r10+184], r8
+ sbb r9, 0
+ sub r11, 96
+ ; Add in place
+ mov rax, QWORD PTR [r11]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [r11+96]
+ mov QWORD PTR [r11+88], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r11+184], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+288], r9
+ ; Add in place
+ mov rax, QWORD PTR [r11+96]
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r11+192]
+ mov QWORD PTR [r11+184], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r11+192], rax
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+104]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+112]
+ mov QWORD PTR [r11+200], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r11+208], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+128]
+ mov QWORD PTR [r11+216], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+136]
+ mov QWORD PTR [r11+224], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [r11+232], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+152]
+ mov QWORD PTR [r11+240], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [r11+248], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r11+256], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [r11+264], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+184]
+ mov QWORD PTR [r11+272], r8
+ adc rax, 0
+ mov QWORD PTR [r11+280], rax
+ add rsp, 504
+ pop r12
+ ret
+sp_3072_sqr_24 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_avx2_24 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 616
+ mov QWORD PTR [rsp+576], rcx
+ mov QWORD PTR [rsp+584], rdx
+ mov QWORD PTR [rsp+592], r8
+ lea r12, QWORD PTR [rsp+384]
+ lea r14, QWORD PTR [rdx+96]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov QWORD PTR [r12+88], r10
+ adc r15, 0
+ mov QWORD PTR [rsp+600], r15
+ lea r13, QWORD PTR [rsp+480]
+ lea r14, QWORD PTR [r8+96]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov QWORD PTR [r13+88], r10
+ adc rdi, 0
+ mov QWORD PTR [rsp+608], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_3072_mul_avx2_12
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ lea rcx, QWORD PTR [rsp+192]
+ add r8, 96
+ add rdx, 96
+ call sp_3072_mul_avx2_12
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ mov rcx, QWORD PTR [rsp+576]
+ call sp_3072_mul_avx2_12
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+592]
+ mov rdx, QWORD PTR [rsp+584]
+ mov rcx, QWORD PTR [rsp+576]
+ENDIF
+ mov r15, QWORD PTR [rsp+600]
+ mov rdi, QWORD PTR [rsp+608]
+ mov rsi, QWORD PTR [rsp+576]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+384]
+ lea r13, QWORD PTR [rsp+480]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 192
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ add rax, r9
+ mov r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [r13+8]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [r13+16]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+8], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+16], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [r13+32]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+24], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [r13+40]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+32], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+40], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [r13+56]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+48], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [r13+64]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+56], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+64], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [r13+80]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+72], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [r13+88]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+80], r9
+ adc r10, rax
+ mov QWORD PTR [rsi+88], r10
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+192]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov QWORD PTR [r12+184], r10
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov QWORD PTR [r12+184], r10
+ sbb r11, 0
+ sub rsi, 96
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov QWORD PTR [rsi+184], r10
+ adc r11, 0
+ mov QWORD PTR [rcx+288], r11
+ add rsi, 96
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov QWORD PTR [rsi+96], rax
+ ; Add to zero
+ mov rax, QWORD PTR [r13+104]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+112]
+ mov QWORD PTR [rsi+104], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+120]
+ mov QWORD PTR [rsi+112], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+128]
+ mov QWORD PTR [rsi+120], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+136]
+ mov QWORD PTR [rsi+128], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+144]
+ mov QWORD PTR [rsi+136], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+152]
+ mov QWORD PTR [rsi+144], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+160]
+ mov QWORD PTR [rsi+152], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+168]
+ mov QWORD PTR [rsi+160], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+176]
+ mov QWORD PTR [rsi+168], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+184]
+ mov QWORD PTR [rsi+176], rax
+ adc r9, 0
+ mov QWORD PTR [rsi+184], r9
+ add rsp, 616
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_avx2_24 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_avx2_24 PROC
+ push r12
+ sub rsp, 504
+ mov QWORD PTR [rsp+480], rcx
+ mov QWORD PTR [rsp+488], rdx
+ lea r10, QWORD PTR [rsp+384]
+ lea r11, QWORD PTR [rdx+96]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r10+88], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+496], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_3072_sqr_avx2_12
+ mov rdx, QWORD PTR [rsp+488]
+ lea rcx, QWORD PTR [rsp+192]
+ add rdx, 96
+ call sp_3072_sqr_avx2_12
+ mov rdx, QWORD PTR [rsp+488]
+ mov rcx, QWORD PTR [rsp+480]
+ call sp_3072_sqr_avx2_12
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+488]
+ mov rcx, QWORD PTR [rsp+480]
+ENDIF
+ mov r12, QWORD PTR [rsp+496]
+ mov r11, rcx
+ lea r10, QWORD PTR [rsp+384]
+ mov r9, r12
+ neg r12
+ add r11, 192
+ mov rax, QWORD PTR [r10]
+ pext rax, rax, r12
+ add rax, rax
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r11], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r11+8], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r11+16], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r11+24], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r11+32], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r11+40], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r11+48], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r11+56], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r11+64], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r11+72], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r11+80], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov QWORD PTR [r11+88], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+192]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+184], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov QWORD PTR [r10+184], r8
+ sbb r9, 0
+ sub r11, 96
+ ; Add in place
+ mov rax, QWORD PTR [r11]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [r11+96]
+ mov QWORD PTR [r11+88], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r11+184], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+288], r9
+ ; Add in place
+ mov rax, QWORD PTR [r11+96]
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r11+192]
+ mov QWORD PTR [r11+184], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r11+192], rax
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+104]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+112]
+ mov QWORD PTR [r11+200], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r11+208], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+128]
+ mov QWORD PTR [r11+216], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+136]
+ mov QWORD PTR [r11+224], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [r11+232], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+152]
+ mov QWORD PTR [r11+240], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [r11+248], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r11+256], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [r11+264], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+184]
+ mov QWORD PTR [r11+272], r8
+ adc rax, 0
+ mov QWORD PTR [r11+280], rax
+ add rsp, 504
+ pop r12
+ ret
+sp_3072_sqr_avx2_24 ENDP
+_text ENDS
+ENDIF
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sub_in_place_48 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rcx+120], r9
+ sbb r8, QWORD PTR [rdx+128]
+ mov r9, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], r8
+ sbb r9, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r9
+ sbb r8, QWORD PTR [rdx+144]
+ mov r9, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], r8
+ sbb r9, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r9
+ sbb r8, QWORD PTR [rdx+160]
+ mov r9, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], r8
+ sbb r9, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r9
+ sbb r8, QWORD PTR [rdx+176]
+ mov r9, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], r8
+ sbb r9, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rcx+184], r9
+ sbb r8, QWORD PTR [rdx+192]
+ mov r9, QWORD PTR [rcx+200]
+ mov QWORD PTR [rcx+192], r8
+ sbb r9, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rcx+200], r9
+ sbb r8, QWORD PTR [rdx+208]
+ mov r9, QWORD PTR [rcx+216]
+ mov QWORD PTR [rcx+208], r8
+ sbb r9, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rcx+216], r9
+ sbb r8, QWORD PTR [rdx+224]
+ mov r9, QWORD PTR [rcx+232]
+ mov QWORD PTR [rcx+224], r8
+ sbb r9, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rcx+232], r9
+ sbb r8, QWORD PTR [rdx+240]
+ mov r9, QWORD PTR [rcx+248]
+ mov QWORD PTR [rcx+240], r8
+ sbb r9, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rcx+256]
+ mov QWORD PTR [rcx+248], r9
+ sbb r8, QWORD PTR [rdx+256]
+ mov r9, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], r8
+ sbb r9, QWORD PTR [rdx+264]
+ mov r8, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r9
+ sbb r8, QWORD PTR [rdx+272]
+ mov r9, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], r8
+ sbb r9, QWORD PTR [rdx+280]
+ mov r8, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r9
+ sbb r8, QWORD PTR [rdx+288]
+ mov r9, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], r8
+ sbb r9, QWORD PTR [rdx+296]
+ mov r8, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r9
+ sbb r8, QWORD PTR [rdx+304]
+ mov r9, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], r8
+ sbb r9, QWORD PTR [rdx+312]
+ mov r8, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r9
+ sbb r8, QWORD PTR [rdx+320]
+ mov r9, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], r8
+ sbb r9, QWORD PTR [rdx+328]
+ mov r8, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r9
+ sbb r8, QWORD PTR [rdx+336]
+ mov r9, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], r8
+ sbb r9, QWORD PTR [rdx+344]
+ mov r8, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r9
+ sbb r8, QWORD PTR [rdx+352]
+ mov r9, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], r8
+ sbb r9, QWORD PTR [rdx+360]
+ mov r8, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r9
+ sbb r8, QWORD PTR [rdx+368]
+ mov r9, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], r8
+ sbb r9, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+376], r9
+ sbb rax, 0
+ ret
+sp_3072_sub_in_place_48 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_add_48 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ adc r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ adc r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ adc r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ adc r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ adc r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ adc r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ adc r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ adc r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ adc r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ adc r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ adc r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ adc r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ adc r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ adc r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ adc r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ adc r10, QWORD PTR [r8+248]
+ mov r9, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+248], r10
+ adc r9, QWORD PTR [r8+256]
+ mov r10, QWORD PTR [rdx+264]
+ mov QWORD PTR [rcx+256], r9
+ adc r10, QWORD PTR [r8+264]
+ mov r9, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+264], r10
+ adc r9, QWORD PTR [r8+272]
+ mov r10, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+272], r9
+ adc r10, QWORD PTR [r8+280]
+ mov r9, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+280], r10
+ adc r9, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+288], r9
+ adc r10, QWORD PTR [r8+296]
+ mov r9, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+296], r10
+ adc r9, QWORD PTR [r8+304]
+ mov r10, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+304], r9
+ adc r10, QWORD PTR [r8+312]
+ mov r9, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+312], r10
+ adc r9, QWORD PTR [r8+320]
+ mov r10, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+320], r9
+ adc r10, QWORD PTR [r8+328]
+ mov r9, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+328], r10
+ adc r9, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+336], r9
+ adc r10, QWORD PTR [r8+344]
+ mov r9, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+344], r10
+ adc r9, QWORD PTR [r8+352]
+ mov r10, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+352], r9
+ adc r10, QWORD PTR [r8+360]
+ mov r9, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+360], r10
+ adc r9, QWORD PTR [r8+368]
+ mov r10, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+368], r9
+ adc r10, QWORD PTR [r8+376]
+ mov QWORD PTR [rcx+376], r10
+ adc rax, 0
+ ret
+sp_3072_add_48 ENDP
+_text ENDS
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_48 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 1192
+ mov QWORD PTR [rsp+1152], rcx
+ mov QWORD PTR [rsp+1160], rdx
+ mov QWORD PTR [rsp+1168], r8
+ lea r12, QWORD PTR [rsp+768]
+ lea r14, QWORD PTR [rdx+192]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [r12+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [r12+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r12+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [r12+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [rdx+160]
+ mov QWORD PTR [r12+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r12+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [r12+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [r12+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov QWORD PTR [r12+184], r10
+ adc r15, 0
+ mov QWORD PTR [rsp+1176], r15
+ lea r13, QWORD PTR [rsp+960]
+ lea r14, QWORD PTR [r8+192]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [r8+128]
+ mov QWORD PTR [r13+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [r8+136]
+ mov QWORD PTR [r13+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [r8+144]
+ mov QWORD PTR [r13+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [r8+152]
+ mov QWORD PTR [r13+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [r8+160]
+ mov QWORD PTR [r13+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [r8+168]
+ mov QWORD PTR [r13+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [r8+176]
+ mov QWORD PTR [r13+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [r8+184]
+ mov QWORD PTR [r13+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov QWORD PTR [r13+184], r10
+ adc rdi, 0
+ mov QWORD PTR [rsp+1184], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_3072_mul_24
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ lea rcx, QWORD PTR [rsp+384]
+ add r8, 192
+ add rdx, 192
+ call sp_3072_mul_24
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ mov rcx, QWORD PTR [rsp+1152]
+ call sp_3072_mul_24
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ mov rcx, QWORD PTR [rsp+1152]
+ENDIF
+ mov r15, QWORD PTR [rsp+1176]
+ mov rdi, QWORD PTR [rsp+1184]
+ mov rsi, QWORD PTR [rsp+1152]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+768]
+ lea r13, QWORD PTR [rsp+960]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 384
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12], rax
+ mov QWORD PTR [r13], r9
+ mov rax, QWORD PTR [r12+8]
+ mov r9, QWORD PTR [r13+8]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+8], rax
+ mov QWORD PTR [r13+8], r9
+ mov rax, QWORD PTR [r12+16]
+ mov r9, QWORD PTR [r13+16]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+16], rax
+ mov QWORD PTR [r13+16], r9
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+24], rax
+ mov QWORD PTR [r13+24], r9
+ mov rax, QWORD PTR [r12+32]
+ mov r9, QWORD PTR [r13+32]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+32], rax
+ mov QWORD PTR [r13+32], r9
+ mov rax, QWORD PTR [r12+40]
+ mov r9, QWORD PTR [r13+40]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+40], rax
+ mov QWORD PTR [r13+40], r9
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+48], rax
+ mov QWORD PTR [r13+48], r9
+ mov rax, QWORD PTR [r12+56]
+ mov r9, QWORD PTR [r13+56]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+56], rax
+ mov QWORD PTR [r13+56], r9
+ mov rax, QWORD PTR [r12+64]
+ mov r9, QWORD PTR [r13+64]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+64], rax
+ mov QWORD PTR [r13+64], r9
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+72], rax
+ mov QWORD PTR [r13+72], r9
+ mov rax, QWORD PTR [r12+80]
+ mov r9, QWORD PTR [r13+80]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+80], rax
+ mov QWORD PTR [r13+80], r9
+ mov rax, QWORD PTR [r12+88]
+ mov r9, QWORD PTR [r13+88]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+88], rax
+ mov QWORD PTR [r13+88], r9
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+96], rax
+ mov QWORD PTR [r13+96], r9
+ mov rax, QWORD PTR [r12+104]
+ mov r9, QWORD PTR [r13+104]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+104], rax
+ mov QWORD PTR [r13+104], r9
+ mov rax, QWORD PTR [r12+112]
+ mov r9, QWORD PTR [r13+112]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+112], rax
+ mov QWORD PTR [r13+112], r9
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+120], rax
+ mov QWORD PTR [r13+120], r9
+ mov rax, QWORD PTR [r12+128]
+ mov r9, QWORD PTR [r13+128]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+128], rax
+ mov QWORD PTR [r13+128], r9
+ mov rax, QWORD PTR [r12+136]
+ mov r9, QWORD PTR [r13+136]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+136], rax
+ mov QWORD PTR [r13+136], r9
+ mov rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [r13+144]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+144], rax
+ mov QWORD PTR [r13+144], r9
+ mov rax, QWORD PTR [r12+152]
+ mov r9, QWORD PTR [r13+152]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+152], rax
+ mov QWORD PTR [r13+152], r9
+ mov rax, QWORD PTR [r12+160]
+ mov r9, QWORD PTR [r13+160]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+160], rax
+ mov QWORD PTR [r13+160], r9
+ mov rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [r13+168]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+168], rax
+ mov QWORD PTR [r13+168], r9
+ mov rax, QWORD PTR [r12+176]
+ mov r9, QWORD PTR [r13+176]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+176], rax
+ mov QWORD PTR [r13+176], r9
+ mov rax, QWORD PTR [r12+184]
+ mov r9, QWORD PTR [r13+184]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+184], rax
+ mov QWORD PTR [r13+184], r9
+ mov rax, QWORD PTR [r12]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov QWORD PTR [rsi+184], r10
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+384]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [r13+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [r13+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [r13+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [r13+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [r13+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [r13+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [r13+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [r13+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [r13+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [r13+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [r13+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [r13+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [r13+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [r13+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [r13+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [r13+376]
+ mov QWORD PTR [r12+376], r10
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [rcx+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [rcx+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [rcx+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [rcx+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [rcx+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [rcx+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [rcx+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [rcx+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [rcx+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [rcx+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [rcx+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [rcx+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [rcx+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [rcx+376]
+ mov QWORD PTR [r12+376], r10
+ sbb r11, 0
+ sub rsi, 192
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r12+256]
+ mov rax, QWORD PTR [rsi+264]
+ mov QWORD PTR [rsi+256], r10
+ adc rax, QWORD PTR [r12+264]
+ mov r9, QWORD PTR [rsi+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, QWORD PTR [r12+272]
+ mov r10, QWORD PTR [rsi+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, QWORD PTR [r12+280]
+ mov rax, QWORD PTR [rsi+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, QWORD PTR [r12+288]
+ mov r9, QWORD PTR [rsi+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, QWORD PTR [r12+296]
+ mov r10, QWORD PTR [rsi+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, QWORD PTR [r12+304]
+ mov rax, QWORD PTR [rsi+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, QWORD PTR [r12+312]
+ mov r9, QWORD PTR [rsi+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, QWORD PTR [r12+320]
+ mov r10, QWORD PTR [rsi+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, QWORD PTR [r12+328]
+ mov rax, QWORD PTR [rsi+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, QWORD PTR [r12+336]
+ mov r9, QWORD PTR [rsi+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, QWORD PTR [r12+344]
+ mov r10, QWORD PTR [rsi+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, QWORD PTR [r12+352]
+ mov rax, QWORD PTR [rsi+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, QWORD PTR [r12+360]
+ mov r9, QWORD PTR [rsi+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, QWORD PTR [r12+368]
+ mov r10, QWORD PTR [rsi+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, QWORD PTR [r12+376]
+ mov QWORD PTR [rsi+376], r10
+ adc r11, 0
+ mov QWORD PTR [rcx+576], r11
+ add rsi, 192
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r13+192]
+ mov QWORD PTR [rsi+192], rax
+ ; Add to zero
+ mov rax, QWORD PTR [r13+200]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+208]
+ mov QWORD PTR [rsi+200], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+216]
+ mov QWORD PTR [rsi+208], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+224]
+ mov QWORD PTR [rsi+216], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+232]
+ mov QWORD PTR [rsi+224], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+240]
+ mov QWORD PTR [rsi+232], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+248]
+ mov QWORD PTR [rsi+240], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+256]
+ mov QWORD PTR [rsi+248], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+264]
+ mov QWORD PTR [rsi+256], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+272]
+ mov QWORD PTR [rsi+264], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+280]
+ mov QWORD PTR [rsi+272], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+288]
+ mov QWORD PTR [rsi+280], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+296]
+ mov QWORD PTR [rsi+288], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+304]
+ mov QWORD PTR [rsi+296], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+312]
+ mov QWORD PTR [rsi+304], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+320]
+ mov QWORD PTR [rsi+312], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+328]
+ mov QWORD PTR [rsi+320], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+336]
+ mov QWORD PTR [rsi+328], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+344]
+ mov QWORD PTR [rsi+336], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+352]
+ mov QWORD PTR [rsi+344], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+360]
+ mov QWORD PTR [rsi+352], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+368]
+ mov QWORD PTR [rsi+360], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+376]
+ mov QWORD PTR [rsi+368], rax
+ adc r9, 0
+ mov QWORD PTR [rsi+376], r9
+ add rsp, 1192
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_48 ENDP
+_text ENDS
+; /* Add a to a into r. (r = a + a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_dbl_24 PROC
+ mov r8, QWORD PTR [rdx]
+ xor rax, rax
+ add r8, r8
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r8
+ adc r9, r9
+ mov QWORD PTR [rcx+184], r9
+ adc rax, 0
+ ret
+sp_3072_dbl_24 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_48 PROC
+ push r12
+ sub rsp, 984
+ mov QWORD PTR [rsp+960], rcx
+ mov QWORD PTR [rsp+968], rdx
+ lea r10, QWORD PTR [rsp+768]
+ lea r11, QWORD PTR [rdx+192]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [r10+120], r8
+ adc rax, QWORD PTR [r11+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov QWORD PTR [r10+128], rax
+ adc r8, QWORD PTR [r11+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r10+136], r8
+ adc rax, QWORD PTR [r11+144]
+ mov r8, QWORD PTR [rdx+152]
+ mov QWORD PTR [r10+144], rax
+ adc r8, QWORD PTR [r11+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov QWORD PTR [r10+152], r8
+ adc rax, QWORD PTR [r11+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov QWORD PTR [r10+160], rax
+ adc r8, QWORD PTR [r11+168]
+ mov rax, QWORD PTR [rdx+176]
+ mov QWORD PTR [r10+168], r8
+ adc rax, QWORD PTR [r11+176]
+ mov r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+176], rax
+ adc r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r10+184], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+976], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_3072_sqr_24
+ mov rdx, QWORD PTR [rsp+968]
+ lea rcx, QWORD PTR [rsp+384]
+ add rdx, 192
+ call sp_3072_sqr_24
+ mov rdx, QWORD PTR [rsp+968]
+ mov rcx, QWORD PTR [rsp+960]
+ call sp_3072_sqr_24
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+968]
+ mov rcx, QWORD PTR [rsp+960]
+ENDIF
+ mov r12, QWORD PTR [rsp+976]
+ mov r11, rcx
+ lea r10, QWORD PTR [rsp+768]
+ mov r9, r12
+ neg r12
+ add r11, 384
+ mov rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r10+8]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11], rax
+ mov QWORD PTR [r11+8], r8
+ mov rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r10+24]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+16], rax
+ mov QWORD PTR [r11+24], r8
+ mov rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r10+40]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+32], rax
+ mov QWORD PTR [r11+40], r8
+ mov rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r10+56]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+48], rax
+ mov QWORD PTR [r11+56], r8
+ mov rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r10+72]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+64], rax
+ mov QWORD PTR [r11+72], r8
+ mov rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r10+88]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+80], rax
+ mov QWORD PTR [r11+88], r8
+ mov rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r10+104]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+96], rax
+ mov QWORD PTR [r11+104], r8
+ mov rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r10+120]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+112], rax
+ mov QWORD PTR [r11+120], r8
+ mov rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r10+136]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+128], rax
+ mov QWORD PTR [r11+136], r8
+ mov rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r10+152]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+144], rax
+ mov QWORD PTR [r11+152], r8
+ mov rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r10+168]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+160], rax
+ mov QWORD PTR [r11+168], r8
+ mov rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r10+184]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [r11+176], rax
+ mov QWORD PTR [r11+184], r8
+ mov rax, QWORD PTR [r11]
+ add rax, rax
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+96]
+ mov QWORD PTR [r11+88], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, r8
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, rax
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, r8
+ mov QWORD PTR [r11+184], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+384]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rdx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rdx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rdx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rdx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rdx+376]
+ mov QWORD PTR [r10+376], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rcx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rcx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rcx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rcx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rcx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rcx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rcx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rcx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rcx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rcx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rcx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rcx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rcx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [r10+376], r8
+ sbb r9, 0
+ sub r11, 192
+ ; Add in place
+ mov rax, QWORD PTR [r11]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [r11+96]
+ mov QWORD PTR [r11+88], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [r11+192]
+ mov QWORD PTR [r11+184], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [r11+200]
+ mov QWORD PTR [r11+192], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [r11+208]
+ mov QWORD PTR [r11+200], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [r11+216]
+ mov QWORD PTR [r11+208], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [r11+224]
+ mov QWORD PTR [r11+216], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [r11+232]
+ mov QWORD PTR [r11+224], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [r11+240]
+ mov QWORD PTR [r11+232], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r11+240], rax
+ adc r8, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [r11+256]
+ mov QWORD PTR [r11+248], r8
+ adc rax, QWORD PTR [r10+256]
+ mov r8, QWORD PTR [r11+264]
+ mov QWORD PTR [r11+256], rax
+ adc r8, QWORD PTR [r10+264]
+ mov rax, QWORD PTR [r11+272]
+ mov QWORD PTR [r11+264], r8
+ adc rax, QWORD PTR [r10+272]
+ mov r8, QWORD PTR [r11+280]
+ mov QWORD PTR [r11+272], rax
+ adc r8, QWORD PTR [r10+280]
+ mov rax, QWORD PTR [r11+288]
+ mov QWORD PTR [r11+280], r8
+ adc rax, QWORD PTR [r10+288]
+ mov r8, QWORD PTR [r11+296]
+ mov QWORD PTR [r11+288], rax
+ adc r8, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [r11+304]
+ mov QWORD PTR [r11+296], r8
+ adc rax, QWORD PTR [r10+304]
+ mov r8, QWORD PTR [r11+312]
+ mov QWORD PTR [r11+304], rax
+ adc r8, QWORD PTR [r10+312]
+ mov rax, QWORD PTR [r11+320]
+ mov QWORD PTR [r11+312], r8
+ adc rax, QWORD PTR [r10+320]
+ mov r8, QWORD PTR [r11+328]
+ mov QWORD PTR [r11+320], rax
+ adc r8, QWORD PTR [r10+328]
+ mov rax, QWORD PTR [r11+336]
+ mov QWORD PTR [r11+328], r8
+ adc rax, QWORD PTR [r10+336]
+ mov r8, QWORD PTR [r11+344]
+ mov QWORD PTR [r11+336], rax
+ adc r8, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [r11+352]
+ mov QWORD PTR [r11+344], r8
+ adc rax, QWORD PTR [r10+352]
+ mov r8, QWORD PTR [r11+360]
+ mov QWORD PTR [r11+352], rax
+ adc r8, QWORD PTR [r10+360]
+ mov rax, QWORD PTR [r11+368]
+ mov QWORD PTR [r11+360], r8
+ adc rax, QWORD PTR [r10+368]
+ mov r8, QWORD PTR [r11+376]
+ mov QWORD PTR [r11+368], rax
+ adc r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r11+376], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+576], r9
+ ; Add in place
+ mov rax, QWORD PTR [r11+192]
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r11+200]
+ mov QWORD PTR [r11+192], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r11+208]
+ mov QWORD PTR [r11+200], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r11+216]
+ mov QWORD PTR [r11+208], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r11+224]
+ mov QWORD PTR [r11+216], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r11+232]
+ mov QWORD PTR [r11+224], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r11+240]
+ mov QWORD PTR [r11+232], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r11+240], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r11+256]
+ mov QWORD PTR [r11+248], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r11+264]
+ mov QWORD PTR [r11+256], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r11+272]
+ mov QWORD PTR [r11+264], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r11+280]
+ mov QWORD PTR [r11+272], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r11+288]
+ mov QWORD PTR [r11+280], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r11+296]
+ mov QWORD PTR [r11+288], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r11+304]
+ mov QWORD PTR [r11+296], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r11+312]
+ mov QWORD PTR [r11+304], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r11+320]
+ mov QWORD PTR [r11+312], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r11+328]
+ mov QWORD PTR [r11+320], rax
+ adc r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r11+336]
+ mov QWORD PTR [r11+328], r8
+ adc rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r11+344]
+ mov QWORD PTR [r11+336], rax
+ adc r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r11+352]
+ mov QWORD PTR [r11+344], r8
+ adc rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r11+360]
+ mov QWORD PTR [r11+352], rax
+ adc r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r11+368]
+ mov QWORD PTR [r11+360], r8
+ adc rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r11+376]
+ mov QWORD PTR [r11+368], rax
+ adc r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r11+384]
+ mov QWORD PTR [r11+376], r8
+ adc rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r11+384], rax
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+200]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+208]
+ mov QWORD PTR [r11+392], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [r11+400], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+224]
+ mov QWORD PTR [r11+408], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+232]
+ mov QWORD PTR [r11+416], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+240]
+ mov QWORD PTR [r11+424], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+248]
+ mov QWORD PTR [r11+432], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+256]
+ mov QWORD PTR [r11+440], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+264]
+ mov QWORD PTR [r11+448], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+272]
+ mov QWORD PTR [r11+456], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+280]
+ mov QWORD PTR [r11+464], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+288]
+ mov QWORD PTR [r11+472], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+296]
+ mov QWORD PTR [r11+480], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+304]
+ mov QWORD PTR [r11+488], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+312]
+ mov QWORD PTR [r11+496], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+320]
+ mov QWORD PTR [r11+504], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+328]
+ mov QWORD PTR [r11+512], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+336]
+ mov QWORD PTR [r11+520], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+344]
+ mov QWORD PTR [r11+528], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+352]
+ mov QWORD PTR [r11+536], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+360]
+ mov QWORD PTR [r11+544], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+368]
+ mov QWORD PTR [r11+552], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+376]
+ mov QWORD PTR [r11+560], r8
+ adc rax, 0
+ mov QWORD PTR [r11+568], rax
+ add rsp, 984
+ pop r12
+ ret
+sp_3072_sqr_48 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_avx2_48 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 1192
+ mov QWORD PTR [rsp+1152], rcx
+ mov QWORD PTR [rsp+1160], rdx
+ mov QWORD PTR [rsp+1168], r8
+ lea r12, QWORD PTR [rsp+768]
+ lea r14, QWORD PTR [rdx+192]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [r12+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [r12+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r12+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [r12+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [rdx+160]
+ mov QWORD PTR [r12+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r12+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [r12+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [r12+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov QWORD PTR [r12+184], r10
+ adc r15, 0
+ mov QWORD PTR [rsp+1176], r15
+ lea r13, QWORD PTR [rsp+960]
+ lea r14, QWORD PTR [r8+192]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [r8+128]
+ mov QWORD PTR [r13+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [r8+136]
+ mov QWORD PTR [r13+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [r8+144]
+ mov QWORD PTR [r13+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [r8+152]
+ mov QWORD PTR [r13+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [r8+160]
+ mov QWORD PTR [r13+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [r8+168]
+ mov QWORD PTR [r13+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [r8+176]
+ mov QWORD PTR [r13+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [r8+184]
+ mov QWORD PTR [r13+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov QWORD PTR [r13+184], r10
+ adc rdi, 0
+ mov QWORD PTR [rsp+1184], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_3072_mul_avx2_24
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ lea rcx, QWORD PTR [rsp+384]
+ add r8, 192
+ add rdx, 192
+ call sp_3072_mul_avx2_24
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ mov rcx, QWORD PTR [rsp+1152]
+ call sp_3072_mul_avx2_24
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+1168]
+ mov rdx, QWORD PTR [rsp+1160]
+ mov rcx, QWORD PTR [rsp+1152]
+ENDIF
+ mov r15, QWORD PTR [rsp+1176]
+ mov rdi, QWORD PTR [rsp+1184]
+ mov rsi, QWORD PTR [rsp+1152]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+768]
+ lea r13, QWORD PTR [rsp+960]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 384
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ add rax, r9
+ mov r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [r13+8]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [r13+16]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+8], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+16], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [r13+32]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+24], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [r13+40]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+32], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+40], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [r13+56]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+48], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [r13+64]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+56], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+64], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [r13+80]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+72], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [r13+88]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+80], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+88], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [r13+104]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+96], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [r13+112]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+104], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+112], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [r13+128]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+120], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [r13+136]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+128], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [r13+144]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+136], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [r13+152]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+144], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [r13+160]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+152], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [r13+168]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+160], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [r13+176]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+168], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [r13+184]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+176], r9
+ adc r10, rax
+ mov QWORD PTR [rsi+184], r10
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+384]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [r13+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [r13+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [r13+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [r13+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [r13+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [r13+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [r13+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [r13+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [r13+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [r13+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [r13+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [r13+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [r13+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [r13+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [r13+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [r13+376]
+ mov QWORD PTR [r12+376], r10
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [rcx+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [rcx+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [rcx+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [rcx+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [rcx+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [rcx+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [rcx+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [rcx+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [rcx+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [rcx+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [rcx+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [rcx+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [rcx+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [rcx+376]
+ mov QWORD PTR [r12+376], r10
+ sbb r11, 0
+ sub rsi, 192
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r12+256]
+ mov rax, QWORD PTR [rsi+264]
+ mov QWORD PTR [rsi+256], r10
+ adc rax, QWORD PTR [r12+264]
+ mov r9, QWORD PTR [rsi+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, QWORD PTR [r12+272]
+ mov r10, QWORD PTR [rsi+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, QWORD PTR [r12+280]
+ mov rax, QWORD PTR [rsi+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, QWORD PTR [r12+288]
+ mov r9, QWORD PTR [rsi+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, QWORD PTR [r12+296]
+ mov r10, QWORD PTR [rsi+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, QWORD PTR [r12+304]
+ mov rax, QWORD PTR [rsi+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, QWORD PTR [r12+312]
+ mov r9, QWORD PTR [rsi+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, QWORD PTR [r12+320]
+ mov r10, QWORD PTR [rsi+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, QWORD PTR [r12+328]
+ mov rax, QWORD PTR [rsi+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, QWORD PTR [r12+336]
+ mov r9, QWORD PTR [rsi+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, QWORD PTR [r12+344]
+ mov r10, QWORD PTR [rsi+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, QWORD PTR [r12+352]
+ mov rax, QWORD PTR [rsi+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, QWORD PTR [r12+360]
+ mov r9, QWORD PTR [rsi+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, QWORD PTR [r12+368]
+ mov r10, QWORD PTR [rsi+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, QWORD PTR [r12+376]
+ mov QWORD PTR [rsi+376], r10
+ adc r11, 0
+ mov QWORD PTR [rcx+576], r11
+ add rsi, 192
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r13+192]
+ mov QWORD PTR [rsi+192], rax
+ ; Add to zero
+ mov rax, QWORD PTR [r13+200]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+208]
+ mov QWORD PTR [rsi+200], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+216]
+ mov QWORD PTR [rsi+208], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+224]
+ mov QWORD PTR [rsi+216], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+232]
+ mov QWORD PTR [rsi+224], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+240]
+ mov QWORD PTR [rsi+232], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+248]
+ mov QWORD PTR [rsi+240], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+256]
+ mov QWORD PTR [rsi+248], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+264]
+ mov QWORD PTR [rsi+256], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+272]
+ mov QWORD PTR [rsi+264], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+280]
+ mov QWORD PTR [rsi+272], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+288]
+ mov QWORD PTR [rsi+280], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+296]
+ mov QWORD PTR [rsi+288], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+304]
+ mov QWORD PTR [rsi+296], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+312]
+ mov QWORD PTR [rsi+304], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+320]
+ mov QWORD PTR [rsi+312], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+328]
+ mov QWORD PTR [rsi+320], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+336]
+ mov QWORD PTR [rsi+328], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+344]
+ mov QWORD PTR [rsi+336], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+352]
+ mov QWORD PTR [rsi+344], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+360]
+ mov QWORD PTR [rsi+352], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+368]
+ mov QWORD PTR [rsi+360], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+376]
+ mov QWORD PTR [rsi+368], rax
+ adc r9, 0
+ mov QWORD PTR [rsi+376], r9
+ add rsp, 1192
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_avx2_48 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sqr_avx2_48 PROC
+ push r12
+ sub rsp, 984
+ mov QWORD PTR [rsp+960], rcx
+ mov QWORD PTR [rsp+968], rdx
+ lea r10, QWORD PTR [rsp+768]
+ lea r11, QWORD PTR [rdx+192]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [r10+120], r8
+ adc rax, QWORD PTR [r11+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov QWORD PTR [r10+128], rax
+ adc r8, QWORD PTR [r11+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r10+136], r8
+ adc rax, QWORD PTR [r11+144]
+ mov r8, QWORD PTR [rdx+152]
+ mov QWORD PTR [r10+144], rax
+ adc r8, QWORD PTR [r11+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov QWORD PTR [r10+152], r8
+ adc rax, QWORD PTR [r11+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov QWORD PTR [r10+160], rax
+ adc r8, QWORD PTR [r11+168]
+ mov rax, QWORD PTR [rdx+176]
+ mov QWORD PTR [r10+168], r8
+ adc rax, QWORD PTR [r11+176]
+ mov r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+176], rax
+ adc r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r10+184], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+976], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_3072_sqr_avx2_24
+ mov rdx, QWORD PTR [rsp+968]
+ lea rcx, QWORD PTR [rsp+384]
+ add rdx, 192
+ call sp_3072_sqr_avx2_24
+ mov rdx, QWORD PTR [rsp+968]
+ mov rcx, QWORD PTR [rsp+960]
+ call sp_3072_sqr_avx2_24
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+968]
+ mov rcx, QWORD PTR [rsp+960]
+ENDIF
+ mov r12, QWORD PTR [rsp+976]
+ mov r11, rcx
+ lea r10, QWORD PTR [rsp+768]
+ mov r9, r12
+ neg r12
+ add r11, 384
+ mov rax, QWORD PTR [r10]
+ pext rax, rax, r12
+ add rax, rax
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r11], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r11+8], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r11+16], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r11+24], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r11+32], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r11+40], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r11+48], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r11+56], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r11+64], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r11+72], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r11+80], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r11+88], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r11+96], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r11+104], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r11+112], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r11+120], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r11+128], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r11+136], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r11+144], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r11+152], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r11+160], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r11+168], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r11+176], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov QWORD PTR [r11+184], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+384]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rdx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rdx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rdx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rdx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rdx+376]
+ mov QWORD PTR [r10+376], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rcx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rcx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rcx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rcx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rcx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rcx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rcx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rcx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rcx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rcx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rcx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rcx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rcx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [r10+376], r8
+ sbb r9, 0
+ sub r11, 192
+ ; Add in place
+ mov rax, QWORD PTR [r11]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r11+8]
+ mov QWORD PTR [r11], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [r11+16]
+ mov QWORD PTR [r11+8], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r11+24]
+ mov QWORD PTR [r11+16], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [r11+32]
+ mov QWORD PTR [r11+24], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r11+40]
+ mov QWORD PTR [r11+32], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [r11+48]
+ mov QWORD PTR [r11+40], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r11+56]
+ mov QWORD PTR [r11+48], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r11+64]
+ mov QWORD PTR [r11+56], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r11+72]
+ mov QWORD PTR [r11+64], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [r11+80]
+ mov QWORD PTR [r11+72], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r11+88]
+ mov QWORD PTR [r11+80], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [r11+96]
+ mov QWORD PTR [r11+88], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r11+104]
+ mov QWORD PTR [r11+96], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r11+112]
+ mov QWORD PTR [r11+104], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r11+120]
+ mov QWORD PTR [r11+112], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [r11+128]
+ mov QWORD PTR [r11+120], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r11+136]
+ mov QWORD PTR [r11+128], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [r11+144]
+ mov QWORD PTR [r11+136], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r11+152]
+ mov QWORD PTR [r11+144], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r11+160]
+ mov QWORD PTR [r11+152], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r11+168]
+ mov QWORD PTR [r11+160], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [r11+176]
+ mov QWORD PTR [r11+168], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r11+184]
+ mov QWORD PTR [r11+176], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [r11+192]
+ mov QWORD PTR [r11+184], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [r11+200]
+ mov QWORD PTR [r11+192], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [r11+208]
+ mov QWORD PTR [r11+200], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [r11+216]
+ mov QWORD PTR [r11+208], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [r11+224]
+ mov QWORD PTR [r11+216], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [r11+232]
+ mov QWORD PTR [r11+224], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [r11+240]
+ mov QWORD PTR [r11+232], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r11+240], rax
+ adc r8, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [r11+256]
+ mov QWORD PTR [r11+248], r8
+ adc rax, QWORD PTR [r10+256]
+ mov r8, QWORD PTR [r11+264]
+ mov QWORD PTR [r11+256], rax
+ adc r8, QWORD PTR [r10+264]
+ mov rax, QWORD PTR [r11+272]
+ mov QWORD PTR [r11+264], r8
+ adc rax, QWORD PTR [r10+272]
+ mov r8, QWORD PTR [r11+280]
+ mov QWORD PTR [r11+272], rax
+ adc r8, QWORD PTR [r10+280]
+ mov rax, QWORD PTR [r11+288]
+ mov QWORD PTR [r11+280], r8
+ adc rax, QWORD PTR [r10+288]
+ mov r8, QWORD PTR [r11+296]
+ mov QWORD PTR [r11+288], rax
+ adc r8, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [r11+304]
+ mov QWORD PTR [r11+296], r8
+ adc rax, QWORD PTR [r10+304]
+ mov r8, QWORD PTR [r11+312]
+ mov QWORD PTR [r11+304], rax
+ adc r8, QWORD PTR [r10+312]
+ mov rax, QWORD PTR [r11+320]
+ mov QWORD PTR [r11+312], r8
+ adc rax, QWORD PTR [r10+320]
+ mov r8, QWORD PTR [r11+328]
+ mov QWORD PTR [r11+320], rax
+ adc r8, QWORD PTR [r10+328]
+ mov rax, QWORD PTR [r11+336]
+ mov QWORD PTR [r11+328], r8
+ adc rax, QWORD PTR [r10+336]
+ mov r8, QWORD PTR [r11+344]
+ mov QWORD PTR [r11+336], rax
+ adc r8, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [r11+352]
+ mov QWORD PTR [r11+344], r8
+ adc rax, QWORD PTR [r10+352]
+ mov r8, QWORD PTR [r11+360]
+ mov QWORD PTR [r11+352], rax
+ adc r8, QWORD PTR [r10+360]
+ mov rax, QWORD PTR [r11+368]
+ mov QWORD PTR [r11+360], r8
+ adc rax, QWORD PTR [r10+368]
+ mov r8, QWORD PTR [r11+376]
+ mov QWORD PTR [r11+368], rax
+ adc r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r11+376], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+576], r9
+ ; Add in place
+ mov rax, QWORD PTR [r11+192]
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r11+200]
+ mov QWORD PTR [r11+192], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r11+208]
+ mov QWORD PTR [r11+200], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r11+216]
+ mov QWORD PTR [r11+208], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r11+224]
+ mov QWORD PTR [r11+216], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r11+232]
+ mov QWORD PTR [r11+224], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r11+240]
+ mov QWORD PTR [r11+232], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r11+240], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r11+256]
+ mov QWORD PTR [r11+248], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r11+264]
+ mov QWORD PTR [r11+256], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r11+272]
+ mov QWORD PTR [r11+264], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r11+280]
+ mov QWORD PTR [r11+272], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r11+288]
+ mov QWORD PTR [r11+280], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r11+296]
+ mov QWORD PTR [r11+288], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r11+304]
+ mov QWORD PTR [r11+296], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r11+312]
+ mov QWORD PTR [r11+304], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r11+320]
+ mov QWORD PTR [r11+312], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r11+328]
+ mov QWORD PTR [r11+320], rax
+ adc r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r11+336]
+ mov QWORD PTR [r11+328], r8
+ adc rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r11+344]
+ mov QWORD PTR [r11+336], rax
+ adc r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r11+352]
+ mov QWORD PTR [r11+344], r8
+ adc rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r11+360]
+ mov QWORD PTR [r11+352], rax
+ adc r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r11+368]
+ mov QWORD PTR [r11+360], r8
+ adc rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r11+376]
+ mov QWORD PTR [r11+368], rax
+ adc r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r11+384]
+ mov QWORD PTR [r11+376], r8
+ adc rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r11+384], rax
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+200]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+208]
+ mov QWORD PTR [r11+392], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [r11+400], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+224]
+ mov QWORD PTR [r11+408], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+232]
+ mov QWORD PTR [r11+416], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+240]
+ mov QWORD PTR [r11+424], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+248]
+ mov QWORD PTR [r11+432], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+256]
+ mov QWORD PTR [r11+440], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+264]
+ mov QWORD PTR [r11+448], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+272]
+ mov QWORD PTR [r11+456], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+280]
+ mov QWORD PTR [r11+464], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+288]
+ mov QWORD PTR [r11+472], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+296]
+ mov QWORD PTR [r11+480], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+304]
+ mov QWORD PTR [r11+488], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+312]
+ mov QWORD PTR [r11+496], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+320]
+ mov QWORD PTR [r11+504], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+328]
+ mov QWORD PTR [r11+512], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+336]
+ mov QWORD PTR [r11+520], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+344]
+ mov QWORD PTR [r11+528], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+352]
+ mov QWORD PTR [r11+536], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+360]
+ mov QWORD PTR [r11+544], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+368]
+ mov QWORD PTR [r11+552], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+376]
+ mov QWORD PTR [r11+560], r8
+ adc rax, 0
+ mov QWORD PTR [r11+568], rax
+ add rsp, 984
+ pop r12
+ ret
+sp_3072_sqr_avx2_48 ENDP
+_text ENDS
+ENDIF
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_d_48 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ mov QWORD PTR [rcx+120], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[16] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+128]
+ add r11, rax
+ mov QWORD PTR [rcx+128], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[17] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ add r12, rax
+ mov QWORD PTR [rcx+136], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[18] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ add r10, rax
+ mov QWORD PTR [rcx+144], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[19] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+152]
+ add r11, rax
+ mov QWORD PTR [rcx+152], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[20] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+160]
+ add r12, rax
+ mov QWORD PTR [rcx+160], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[21] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+168]
+ add r10, rax
+ mov QWORD PTR [rcx+168], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[22] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+176]
+ add r11, rax
+ mov QWORD PTR [rcx+176], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[23] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ add r12, rax
+ mov QWORD PTR [rcx+184], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[24] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ add r10, rax
+ mov QWORD PTR [rcx+192], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[25] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+200]
+ add r11, rax
+ mov QWORD PTR [rcx+200], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[26] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+208]
+ add r12, rax
+ mov QWORD PTR [rcx+208], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[27] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+216]
+ add r10, rax
+ mov QWORD PTR [rcx+216], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[28] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+224]
+ add r11, rax
+ mov QWORD PTR [rcx+224], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[29] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ add r12, rax
+ mov QWORD PTR [rcx+232], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[30] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ add r10, rax
+ mov QWORD PTR [rcx+240], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[31] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+248]
+ add r11, rax
+ mov QWORD PTR [rcx+248], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[32] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+256]
+ add r12, rax
+ mov QWORD PTR [rcx+256], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[33] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+264]
+ add r10, rax
+ mov QWORD PTR [rcx+264], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[34] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+272]
+ add r11, rax
+ mov QWORD PTR [rcx+272], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[35] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+280]
+ add r12, rax
+ mov QWORD PTR [rcx+280], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[36] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+288]
+ add r10, rax
+ mov QWORD PTR [rcx+288], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[37] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+296]
+ add r11, rax
+ mov QWORD PTR [rcx+296], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[38] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+304]
+ add r12, rax
+ mov QWORD PTR [rcx+304], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[39] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+312]
+ add r10, rax
+ mov QWORD PTR [rcx+312], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[40] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+320]
+ add r11, rax
+ mov QWORD PTR [rcx+320], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[41] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+328]
+ add r12, rax
+ mov QWORD PTR [rcx+328], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[42] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+336]
+ add r10, rax
+ mov QWORD PTR [rcx+336], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[43] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+344]
+ add r11, rax
+ mov QWORD PTR [rcx+344], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[44] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+352]
+ add r12, rax
+ mov QWORD PTR [rcx+352], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[45] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+360]
+ add r10, rax
+ mov QWORD PTR [rcx+360], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[46] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+368]
+ add r11, rax
+ mov QWORD PTR [rcx+368], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[47] * B
+ mov rax, r8
+ mul QWORD PTR [r9+376]
+ add r12, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+376], r12
+ mov QWORD PTR [rcx+384], r10
+ pop r12
+ ret
+sp_3072_mul_d_48 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_sub_24 PROC
+ sub rsp, 192
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ sbb r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ sbb r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ sbb r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ sbb r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ sbb r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ sbb r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ sbb r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ sbb r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov QWORD PTR [rcx+184], r11
+ sbb rax, 0
+ add rsp, 192
+ ret
+sp_3072_cond_sub_24 ENDP
+_text ENDS
+; /* Reduce the number back to 3072 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mont_reduce_24 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 24
+ mov r10, 24
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_3072_mont_loop_24:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc r11, 0
+ ; a[i+16] += m[16] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+128]
+ mov r14, QWORD PTR [rcx+128]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+128], r14
+ adc r12, 0
+ ; a[i+17] += m[17] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ mov r14, QWORD PTR [rcx+136]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+136], r14
+ adc r11, 0
+ ; a[i+18] += m[18] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ mov r14, QWORD PTR [rcx+144]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+144], r14
+ adc r12, 0
+ ; a[i+19] += m[19] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+152]
+ mov r14, QWORD PTR [rcx+152]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+152], r14
+ adc r11, 0
+ ; a[i+20] += m[20] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+160]
+ mov r14, QWORD PTR [rcx+160]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+160], r14
+ adc r12, 0
+ ; a[i+21] += m[21] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+168]
+ mov r14, QWORD PTR [rcx+168]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+168], r14
+ adc r11, 0
+ ; a[i+22] += m[22] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+176]
+ mov r14, QWORD PTR [rcx+176]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+176], r14
+ adc r12, 0
+ ; a[i+23] += m[23] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+184]
+ mov r14, QWORD PTR [rcx+184]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+184], r14
+ adc QWORD PTR [rcx+192], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_3072_mont_loop_24
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 192
+ call sp_3072_cond_sub_24
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mont_reduce_24 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_sub_avx2_24 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ sbb r12, r10
+ mov QWORD PTR [rcx+184], r12
+ sbb rax, 0
+ pop r12
+ ret
+sp_3072_cond_sub_avx2_24 ENDP
+_text ENDS
+ENDIF
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_d_24 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ mov QWORD PTR [rcx+120], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[16] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+128]
+ add r11, rax
+ mov QWORD PTR [rcx+128], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[17] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ add r12, rax
+ mov QWORD PTR [rcx+136], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[18] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ add r10, rax
+ mov QWORD PTR [rcx+144], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[19] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+152]
+ add r11, rax
+ mov QWORD PTR [rcx+152], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[20] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+160]
+ add r12, rax
+ mov QWORD PTR [rcx+160], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[21] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+168]
+ add r10, rax
+ mov QWORD PTR [rcx+168], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[22] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+176]
+ add r11, rax
+ mov QWORD PTR [rcx+176], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[23] * B
+ mov rax, r8
+ mul QWORD PTR [r9+184]
+ add r12, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+184], r12
+ mov QWORD PTR [rcx+192], r10
+ pop r12
+ ret
+sp_3072_mul_d_24 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_d_avx2_24 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+120], r12
+ ; A[16] * B
+ mulx r10, r9, QWORD PTR [rax+128]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+128], r11
+ ; A[17] * B
+ mulx r10, r9, QWORD PTR [rax+136]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+136], r12
+ ; A[18] * B
+ mulx r10, r9, QWORD PTR [rax+144]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+144], r11
+ ; A[19] * B
+ mulx r10, r9, QWORD PTR [rax+152]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+152], r12
+ ; A[20] * B
+ mulx r10, r9, QWORD PTR [rax+160]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+160], r11
+ ; A[21] * B
+ mulx r10, r9, QWORD PTR [rax+168]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+168], r12
+ ; A[22] * B
+ mulx r10, r9, QWORD PTR [rax+176]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+176], r11
+ ; A[23] * B
+ mulx r10, r9, QWORD PTR [rax+184]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+184], r12
+ mov QWORD PTR [rcx+192], r11
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_d_avx2_24 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_3072_word_asm_24 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_3072_word_asm_24 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cmp_24 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+184]
+ mov r12, QWORD PTR [rdx+184]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+176]
+ mov r12, QWORD PTR [rdx+176]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+168]
+ mov r12, QWORD PTR [rdx+168]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+160]
+ mov r12, QWORD PTR [rdx+160]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+152]
+ mov r12, QWORD PTR [rdx+152]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+144]
+ mov r12, QWORD PTR [rdx+144]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+136]
+ mov r12, QWORD PTR [rdx+136]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+128]
+ mov r12, QWORD PTR [rdx+128]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_3072_cmp_24 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 3072 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mont_reduce_avx2_24 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 24
+ mov r11, 24
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 96
+ xor rbp, rbp
+L_3072_mont_loop_avx2_24:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-64]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-56]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-56], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-48], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+-32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-40], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+-24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-32], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+16] += m[16] * mu
+ mulx rcx, rax, QWORD PTR [r10+128]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+17] += m[17] * mu
+ mulx rcx, rax, QWORD PTR [r10+136]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+18] += m[18] * mu
+ mulx rcx, rax, QWORD PTR [r10+144]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+19] += m[19] * mu
+ mulx rcx, rax, QWORD PTR [r10+152]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ ; a[i+20] += m[20] * mu
+ mulx rcx, rax, QWORD PTR [r10+160]
+ mov r13, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+64], r12
+ ; a[i+21] += m[21] * mu
+ mulx rcx, rax, QWORD PTR [r10+168]
+ mov r12, QWORD PTR [r9+80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+72], r13
+ ; a[i+22] += m[22] * mu
+ mulx rcx, rax, QWORD PTR [r10+176]
+ mov r13, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+80], r12
+ ; a[i+23] += m[23] * mu
+ mulx rcx, rax, QWORD PTR [r10+184]
+ mov r12, QWORD PTR [r9+96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+88], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+96], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 1
+ add r9, 8
+ ; i -= 1
+ sub r11, 1
+ jnz L_3072_mont_loop_avx2_24
+ sub r9, 96
+ neg rbp
+ mov r8, r9
+ sub r9, 192
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+128]
+ mov rax, QWORD PTR [r8+128]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+120], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+136]
+ mov rcx, QWORD PTR [r8+136]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+128], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+144]
+ mov rdx, QWORD PTR [r8+144]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+136], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r8+152]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+144], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+160]
+ mov rcx, QWORD PTR [r8+160]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+152], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+168]
+ mov rdx, QWORD PTR [r8+168]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+160], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+176]
+ mov rax, QWORD PTR [r8+176]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+168], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+184]
+ mov rcx, QWORD PTR [r8+184]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+176], rax
+ sbb rcx, rdx
+ mov QWORD PTR [r9+184], rcx
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mont_reduce_avx2_24 ENDP
+_text ENDS
+ENDIF
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_sub_48 PROC
+ sub rsp, 384
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [r8+192]
+ mov r11, QWORD PTR [r8+200]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+192], r10
+ mov QWORD PTR [rsp+200], r11
+ mov r10, QWORD PTR [r8+208]
+ mov r11, QWORD PTR [r8+216]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+208], r10
+ mov QWORD PTR [rsp+216], r11
+ mov r10, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [r8+232]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+224], r10
+ mov QWORD PTR [rsp+232], r11
+ mov r10, QWORD PTR [r8+240]
+ mov r11, QWORD PTR [r8+248]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+240], r10
+ mov QWORD PTR [rsp+248], r11
+ mov r10, QWORD PTR [r8+256]
+ mov r11, QWORD PTR [r8+264]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+256], r10
+ mov QWORD PTR [rsp+264], r11
+ mov r10, QWORD PTR [r8+272]
+ mov r11, QWORD PTR [r8+280]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+272], r10
+ mov QWORD PTR [rsp+280], r11
+ mov r10, QWORD PTR [r8+288]
+ mov r11, QWORD PTR [r8+296]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+288], r10
+ mov QWORD PTR [rsp+296], r11
+ mov r10, QWORD PTR [r8+304]
+ mov r11, QWORD PTR [r8+312]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+304], r10
+ mov QWORD PTR [rsp+312], r11
+ mov r10, QWORD PTR [r8+320]
+ mov r11, QWORD PTR [r8+328]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+320], r10
+ mov QWORD PTR [rsp+328], r11
+ mov r10, QWORD PTR [r8+336]
+ mov r11, QWORD PTR [r8+344]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+336], r10
+ mov QWORD PTR [rsp+344], r11
+ mov r10, QWORD PTR [r8+352]
+ mov r11, QWORD PTR [r8+360]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+352], r10
+ mov QWORD PTR [rsp+360], r11
+ mov r10, QWORD PTR [r8+368]
+ mov r11, QWORD PTR [r8+376]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+368], r10
+ mov QWORD PTR [rsp+376], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ sbb r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ sbb r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ sbb r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ sbb r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ sbb r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ sbb r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ sbb r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ sbb r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov r10, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rsp+192]
+ sbb r10, r8
+ mov QWORD PTR [rcx+184], r11
+ mov r11, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rsp+200]
+ sbb r11, r8
+ mov QWORD PTR [rcx+192], r10
+ mov r10, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rsp+208]
+ sbb r10, r8
+ mov QWORD PTR [rcx+200], r11
+ mov r11, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rsp+216]
+ sbb r11, r8
+ mov QWORD PTR [rcx+208], r10
+ mov r10, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rsp+224]
+ sbb r10, r8
+ mov QWORD PTR [rcx+216], r11
+ mov r11, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rsp+232]
+ sbb r11, r8
+ mov QWORD PTR [rcx+224], r10
+ mov r10, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rsp+240]
+ sbb r10, r8
+ mov QWORD PTR [rcx+232], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rsp+248]
+ sbb r11, r8
+ mov QWORD PTR [rcx+240], r10
+ mov r10, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [rsp+256]
+ sbb r10, r8
+ mov QWORD PTR [rcx+248], r11
+ mov r11, QWORD PTR [rdx+264]
+ mov r8, QWORD PTR [rsp+264]
+ sbb r11, r8
+ mov QWORD PTR [rcx+256], r10
+ mov r10, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [rsp+272]
+ sbb r10, r8
+ mov QWORD PTR [rcx+264], r11
+ mov r11, QWORD PTR [rdx+280]
+ mov r8, QWORD PTR [rsp+280]
+ sbb r11, r8
+ mov QWORD PTR [rcx+272], r10
+ mov r10, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [rsp+288]
+ sbb r10, r8
+ mov QWORD PTR [rcx+280], r11
+ mov r11, QWORD PTR [rdx+296]
+ mov r8, QWORD PTR [rsp+296]
+ sbb r11, r8
+ mov QWORD PTR [rcx+288], r10
+ mov r10, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [rsp+304]
+ sbb r10, r8
+ mov QWORD PTR [rcx+296], r11
+ mov r11, QWORD PTR [rdx+312]
+ mov r8, QWORD PTR [rsp+312]
+ sbb r11, r8
+ mov QWORD PTR [rcx+304], r10
+ mov r10, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [rsp+320]
+ sbb r10, r8
+ mov QWORD PTR [rcx+312], r11
+ mov r11, QWORD PTR [rdx+328]
+ mov r8, QWORD PTR [rsp+328]
+ sbb r11, r8
+ mov QWORD PTR [rcx+320], r10
+ mov r10, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [rsp+336]
+ sbb r10, r8
+ mov QWORD PTR [rcx+328], r11
+ mov r11, QWORD PTR [rdx+344]
+ mov r8, QWORD PTR [rsp+344]
+ sbb r11, r8
+ mov QWORD PTR [rcx+336], r10
+ mov r10, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [rsp+352]
+ sbb r10, r8
+ mov QWORD PTR [rcx+344], r11
+ mov r11, QWORD PTR [rdx+360]
+ mov r8, QWORD PTR [rsp+360]
+ sbb r11, r8
+ mov QWORD PTR [rcx+352], r10
+ mov r10, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [rsp+368]
+ sbb r10, r8
+ mov QWORD PTR [rcx+360], r11
+ mov r11, QWORD PTR [rdx+376]
+ mov r8, QWORD PTR [rsp+376]
+ sbb r11, r8
+ mov QWORD PTR [rcx+368], r10
+ mov QWORD PTR [rcx+376], r11
+ sbb rax, 0
+ add rsp, 384
+ ret
+sp_3072_cond_sub_48 ENDP
+_text ENDS
+; /* Reduce the number back to 3072 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mont_reduce_48 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 48
+ mov r10, 48
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_3072_mont_loop_48:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc r11, 0
+ ; a[i+16] += m[16] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+128]
+ mov r14, QWORD PTR [rcx+128]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+128], r14
+ adc r12, 0
+ ; a[i+17] += m[17] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ mov r14, QWORD PTR [rcx+136]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+136], r14
+ adc r11, 0
+ ; a[i+18] += m[18] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ mov r14, QWORD PTR [rcx+144]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+144], r14
+ adc r12, 0
+ ; a[i+19] += m[19] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+152]
+ mov r14, QWORD PTR [rcx+152]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+152], r14
+ adc r11, 0
+ ; a[i+20] += m[20] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+160]
+ mov r14, QWORD PTR [rcx+160]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+160], r14
+ adc r12, 0
+ ; a[i+21] += m[21] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+168]
+ mov r14, QWORD PTR [rcx+168]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+168], r14
+ adc r11, 0
+ ; a[i+22] += m[22] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+176]
+ mov r14, QWORD PTR [rcx+176]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+176], r14
+ adc r12, 0
+ ; a[i+23] += m[23] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ mov r14, QWORD PTR [rcx+184]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+184], r14
+ adc r11, 0
+ ; a[i+24] += m[24] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ mov r14, QWORD PTR [rcx+192]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+192], r14
+ adc r12, 0
+ ; a[i+25] += m[25] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+200]
+ mov r14, QWORD PTR [rcx+200]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+200], r14
+ adc r11, 0
+ ; a[i+26] += m[26] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+208]
+ mov r14, QWORD PTR [rcx+208]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+208], r14
+ adc r12, 0
+ ; a[i+27] += m[27] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+216]
+ mov r14, QWORD PTR [rcx+216]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+216], r14
+ adc r11, 0
+ ; a[i+28] += m[28] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+224]
+ mov r14, QWORD PTR [rcx+224]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+224], r14
+ adc r12, 0
+ ; a[i+29] += m[29] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ mov r14, QWORD PTR [rcx+232]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+232], r14
+ adc r11, 0
+ ; a[i+30] += m[30] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ mov r14, QWORD PTR [rcx+240]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+240], r14
+ adc r12, 0
+ ; a[i+31] += m[31] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+248]
+ mov r14, QWORD PTR [rcx+248]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+248], r14
+ adc r11, 0
+ ; a[i+32] += m[32] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+256]
+ mov r14, QWORD PTR [rcx+256]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+256], r14
+ adc r12, 0
+ ; a[i+33] += m[33] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+264]
+ mov r14, QWORD PTR [rcx+264]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+264], r14
+ adc r11, 0
+ ; a[i+34] += m[34] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+272]
+ mov r14, QWORD PTR [rcx+272]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+272], r14
+ adc r12, 0
+ ; a[i+35] += m[35] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+280]
+ mov r14, QWORD PTR [rcx+280]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+280], r14
+ adc r11, 0
+ ; a[i+36] += m[36] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+288]
+ mov r14, QWORD PTR [rcx+288]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+288], r14
+ adc r12, 0
+ ; a[i+37] += m[37] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+296]
+ mov r14, QWORD PTR [rcx+296]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+296], r14
+ adc r11, 0
+ ; a[i+38] += m[38] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+304]
+ mov r14, QWORD PTR [rcx+304]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+304], r14
+ adc r12, 0
+ ; a[i+39] += m[39] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+312]
+ mov r14, QWORD PTR [rcx+312]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+312], r14
+ adc r11, 0
+ ; a[i+40] += m[40] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+320]
+ mov r14, QWORD PTR [rcx+320]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+320], r14
+ adc r12, 0
+ ; a[i+41] += m[41] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+328]
+ mov r14, QWORD PTR [rcx+328]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+328], r14
+ adc r11, 0
+ ; a[i+42] += m[42] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+336]
+ mov r14, QWORD PTR [rcx+336]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+336], r14
+ adc r12, 0
+ ; a[i+43] += m[43] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+344]
+ mov r14, QWORD PTR [rcx+344]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+344], r14
+ adc r11, 0
+ ; a[i+44] += m[44] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+352]
+ mov r14, QWORD PTR [rcx+352]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+352], r14
+ adc r12, 0
+ ; a[i+45] += m[45] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+360]
+ mov r14, QWORD PTR [rcx+360]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+360], r14
+ adc r11, 0
+ ; a[i+46] += m[46] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+368]
+ mov r14, QWORD PTR [rcx+368]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+368], r14
+ adc r12, 0
+ ; a[i+47] += m[47] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+376]
+ mov r14, QWORD PTR [rcx+376]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+376], r14
+ adc QWORD PTR [rcx+384], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_3072_mont_loop_48
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 384
+ call sp_3072_cond_sub_48
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mont_reduce_48 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_sub_avx2_48 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+192]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+184], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+200]
+ mov r11, QWORD PTR [rdx+200]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+192], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+208]
+ mov r12, QWORD PTR [rdx+208]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+200], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+216]
+ mov r10, QWORD PTR [rdx+216]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+208], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [rdx+224]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+216], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+232]
+ mov r12, QWORD PTR [rdx+232]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+224], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+240]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+232], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+248]
+ mov r11, QWORD PTR [rdx+248]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+240], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+256]
+ mov r12, QWORD PTR [rdx+256]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+248], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+264]
+ mov r10, QWORD PTR [rdx+264]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+256], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+272]
+ mov r11, QWORD PTR [rdx+272]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+264], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+280]
+ mov r12, QWORD PTR [rdx+280]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+272], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+288]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+280], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+296]
+ mov r11, QWORD PTR [rdx+296]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+288], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+304]
+ mov r12, QWORD PTR [rdx+304]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+296], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+312]
+ mov r10, QWORD PTR [rdx+312]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+304], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+320]
+ mov r11, QWORD PTR [rdx+320]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+312], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+328]
+ mov r12, QWORD PTR [rdx+328]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+320], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+336]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+328], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+344]
+ mov r11, QWORD PTR [rdx+344]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+336], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+352]
+ mov r12, QWORD PTR [rdx+352]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+344], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+360]
+ mov r10, QWORD PTR [rdx+360]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+352], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+368]
+ mov r11, QWORD PTR [rdx+368]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+360], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+376]
+ mov r12, QWORD PTR [rdx+376]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+368], r11
+ sbb r12, r10
+ mov QWORD PTR [rcx+376], r12
+ sbb rax, 0
+ pop r12
+ ret
+sp_3072_cond_sub_avx2_48 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mul_d_avx2_48 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+120], r12
+ ; A[16] * B
+ mulx r10, r9, QWORD PTR [rax+128]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+128], r11
+ ; A[17] * B
+ mulx r10, r9, QWORD PTR [rax+136]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+136], r12
+ ; A[18] * B
+ mulx r10, r9, QWORD PTR [rax+144]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+144], r11
+ ; A[19] * B
+ mulx r10, r9, QWORD PTR [rax+152]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+152], r12
+ ; A[20] * B
+ mulx r10, r9, QWORD PTR [rax+160]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+160], r11
+ ; A[21] * B
+ mulx r10, r9, QWORD PTR [rax+168]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+168], r12
+ ; A[22] * B
+ mulx r10, r9, QWORD PTR [rax+176]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+176], r11
+ ; A[23] * B
+ mulx r10, r9, QWORD PTR [rax+184]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+184], r12
+ ; A[24] * B
+ mulx r10, r9, QWORD PTR [rax+192]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+192], r11
+ ; A[25] * B
+ mulx r10, r9, QWORD PTR [rax+200]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+200], r12
+ ; A[26] * B
+ mulx r10, r9, QWORD PTR [rax+208]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+208], r11
+ ; A[27] * B
+ mulx r10, r9, QWORD PTR [rax+216]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+216], r12
+ ; A[28] * B
+ mulx r10, r9, QWORD PTR [rax+224]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+224], r11
+ ; A[29] * B
+ mulx r10, r9, QWORD PTR [rax+232]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+232], r12
+ ; A[30] * B
+ mulx r10, r9, QWORD PTR [rax+240]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+240], r11
+ ; A[31] * B
+ mulx r10, r9, QWORD PTR [rax+248]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+248], r12
+ ; A[32] * B
+ mulx r10, r9, QWORD PTR [rax+256]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+256], r11
+ ; A[33] * B
+ mulx r10, r9, QWORD PTR [rax+264]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+264], r12
+ ; A[34] * B
+ mulx r10, r9, QWORD PTR [rax+272]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+272], r11
+ ; A[35] * B
+ mulx r10, r9, QWORD PTR [rax+280]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+280], r12
+ ; A[36] * B
+ mulx r10, r9, QWORD PTR [rax+288]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+288], r11
+ ; A[37] * B
+ mulx r10, r9, QWORD PTR [rax+296]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+296], r12
+ ; A[38] * B
+ mulx r10, r9, QWORD PTR [rax+304]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+304], r11
+ ; A[39] * B
+ mulx r10, r9, QWORD PTR [rax+312]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+312], r12
+ ; A[40] * B
+ mulx r10, r9, QWORD PTR [rax+320]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+320], r11
+ ; A[41] * B
+ mulx r10, r9, QWORD PTR [rax+328]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+328], r12
+ ; A[42] * B
+ mulx r10, r9, QWORD PTR [rax+336]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+336], r11
+ ; A[43] * B
+ mulx r10, r9, QWORD PTR [rax+344]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+344], r12
+ ; A[44] * B
+ mulx r10, r9, QWORD PTR [rax+352]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+352], r11
+ ; A[45] * B
+ mulx r10, r9, QWORD PTR [rax+360]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+360], r12
+ ; A[46] * B
+ mulx r10, r9, QWORD PTR [rax+368]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+368], r11
+ ; A[47] * B
+ mulx r10, r9, QWORD PTR [rax+376]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+376], r12
+ mov QWORD PTR [rcx+384], r11
+ pop r13
+ pop r12
+ ret
+sp_3072_mul_d_avx2_48 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_3072_word_asm_48 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_3072_word_asm_48 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cmp_48 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+376]
+ mov r12, QWORD PTR [rdx+376]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+368]
+ mov r12, QWORD PTR [rdx+368]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+360]
+ mov r12, QWORD PTR [rdx+360]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+352]
+ mov r12, QWORD PTR [rdx+352]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+344]
+ mov r12, QWORD PTR [rdx+344]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+336]
+ mov r12, QWORD PTR [rdx+336]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+328]
+ mov r12, QWORD PTR [rdx+328]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+320]
+ mov r12, QWORD PTR [rdx+320]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+312]
+ mov r12, QWORD PTR [rdx+312]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+304]
+ mov r12, QWORD PTR [rdx+304]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+296]
+ mov r12, QWORD PTR [rdx+296]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+288]
+ mov r12, QWORD PTR [rdx+288]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+280]
+ mov r12, QWORD PTR [rdx+280]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+272]
+ mov r12, QWORD PTR [rdx+272]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+264]
+ mov r12, QWORD PTR [rdx+264]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+256]
+ mov r12, QWORD PTR [rdx+256]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+248]
+ mov r12, QWORD PTR [rdx+248]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+240]
+ mov r12, QWORD PTR [rdx+240]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+232]
+ mov r12, QWORD PTR [rdx+232]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+224]
+ mov r12, QWORD PTR [rdx+224]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+216]
+ mov r12, QWORD PTR [rdx+216]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+208]
+ mov r12, QWORD PTR [rdx+208]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+200]
+ mov r12, QWORD PTR [rdx+200]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+192]
+ mov r12, QWORD PTR [rdx+192]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+184]
+ mov r12, QWORD PTR [rdx+184]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+176]
+ mov r12, QWORD PTR [rdx+176]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+168]
+ mov r12, QWORD PTR [rdx+168]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+160]
+ mov r12, QWORD PTR [rdx+160]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+152]
+ mov r12, QWORD PTR [rdx+152]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+144]
+ mov r12, QWORD PTR [rdx+144]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+136]
+ mov r12, QWORD PTR [rdx+136]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+128]
+ mov r12, QWORD PTR [rdx+128]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_3072_cmp_48 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_sub_48 PROC
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ sub r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ sbb r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ sbb r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ sbb r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ sbb r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ sbb r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ sbb r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ sbb r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ sbb r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ sbb r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ sbb r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ sbb r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ sbb r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ sbb r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ sbb r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ sbb r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ sbb r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ sbb r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ sbb r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ sbb r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ sbb r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ sbb r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ sbb r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ sbb r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ sbb r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ sbb r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ sbb r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ sbb r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ sbb r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ sbb r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ sbb r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ sbb r10, QWORD PTR [r8+248]
+ mov r9, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+248], r10
+ sbb r9, QWORD PTR [r8+256]
+ mov r10, QWORD PTR [rdx+264]
+ mov QWORD PTR [rcx+256], r9
+ sbb r10, QWORD PTR [r8+264]
+ mov r9, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+264], r10
+ sbb r9, QWORD PTR [r8+272]
+ mov r10, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+272], r9
+ sbb r10, QWORD PTR [r8+280]
+ mov r9, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+280], r10
+ sbb r9, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+288], r9
+ sbb r10, QWORD PTR [r8+296]
+ mov r9, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+296], r10
+ sbb r9, QWORD PTR [r8+304]
+ mov r10, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+304], r9
+ sbb r10, QWORD PTR [r8+312]
+ mov r9, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+312], r10
+ sbb r9, QWORD PTR [r8+320]
+ mov r10, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+320], r9
+ sbb r10, QWORD PTR [r8+328]
+ mov r9, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+328], r10
+ sbb r9, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+336], r9
+ sbb r10, QWORD PTR [r8+344]
+ mov r9, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+344], r10
+ sbb r9, QWORD PTR [r8+352]
+ mov r10, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+352], r9
+ sbb r10, QWORD PTR [r8+360]
+ mov r9, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+360], r10
+ sbb r9, QWORD PTR [r8+368]
+ mov r10, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+368], r9
+ sbb r10, QWORD PTR [r8+376]
+ mov QWORD PTR [rcx+376], r10
+ sbb rax, 0
+ ret
+sp_3072_sub_48 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 3072 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_mont_reduce_avx2_48 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 48
+ mov r11, 48
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 192
+ xor rbp, rbp
+L_3072_mont_loop_avx2_48:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-160]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-152]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-144]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-152], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-136]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-144], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+-128]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-136], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+-120]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-128], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+-112]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-120], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+-104]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-112], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+-96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-104], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+-88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-96], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+-80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-88], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+-72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-80], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+-64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-72], r13
+ ; a[i+16] += m[16] * mu
+ mulx rcx, rax, QWORD PTR [r10+128]
+ mov r13, QWORD PTR [r9+-56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-64], r12
+ ; a[i+17] += m[17] * mu
+ mulx rcx, rax, QWORD PTR [r10+136]
+ mov r12, QWORD PTR [r9+-48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-56], r13
+ ; a[i+18] += m[18] * mu
+ mulx rcx, rax, QWORD PTR [r10+144]
+ mov r13, QWORD PTR [r9+-40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-48], r12
+ ; a[i+19] += m[19] * mu
+ mulx rcx, rax, QWORD PTR [r10+152]
+ mov r12, QWORD PTR [r9+-32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-40], r13
+ ; a[i+20] += m[20] * mu
+ mulx rcx, rax, QWORD PTR [r10+160]
+ mov r13, QWORD PTR [r9+-24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-32], r12
+ ; a[i+21] += m[21] * mu
+ mulx rcx, rax, QWORD PTR [r10+168]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+22] += m[22] * mu
+ mulx rcx, rax, QWORD PTR [r10+176]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+23] += m[23] * mu
+ mulx rcx, rax, QWORD PTR [r10+184]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+24] += m[24] * mu
+ mulx rcx, rax, QWORD PTR [r10+192]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+25] += m[25] * mu
+ mulx rcx, rax, QWORD PTR [r10+200]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+26] += m[26] * mu
+ mulx rcx, rax, QWORD PTR [r10+208]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+27] += m[27] * mu
+ mulx rcx, rax, QWORD PTR [r10+216]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+28] += m[28] * mu
+ mulx rcx, rax, QWORD PTR [r10+224]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+29] += m[29] * mu
+ mulx rcx, rax, QWORD PTR [r10+232]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+30] += m[30] * mu
+ mulx rcx, rax, QWORD PTR [r10+240]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+31] += m[31] * mu
+ mulx rcx, rax, QWORD PTR [r10+248]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ ; a[i+32] += m[32] * mu
+ mulx rcx, rax, QWORD PTR [r10+256]
+ mov r13, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+64], r12
+ ; a[i+33] += m[33] * mu
+ mulx rcx, rax, QWORD PTR [r10+264]
+ mov r12, QWORD PTR [r9+80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+72], r13
+ ; a[i+34] += m[34] * mu
+ mulx rcx, rax, QWORD PTR [r10+272]
+ mov r13, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+80], r12
+ ; a[i+35] += m[35] * mu
+ mulx rcx, rax, QWORD PTR [r10+280]
+ mov r12, QWORD PTR [r9+96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+88], r13
+ ; a[i+36] += m[36] * mu
+ mulx rcx, rax, QWORD PTR [r10+288]
+ mov r13, QWORD PTR [r9+104]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+96], r12
+ ; a[i+37] += m[37] * mu
+ mulx rcx, rax, QWORD PTR [r10+296]
+ mov r12, QWORD PTR [r9+112]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+104], r13
+ ; a[i+38] += m[38] * mu
+ mulx rcx, rax, QWORD PTR [r10+304]
+ mov r13, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+112], r12
+ ; a[i+39] += m[39] * mu
+ mulx rcx, rax, QWORD PTR [r10+312]
+ mov r12, QWORD PTR [r9+128]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+120], r13
+ ; a[i+40] += m[40] * mu
+ mulx rcx, rax, QWORD PTR [r10+320]
+ mov r13, QWORD PTR [r9+136]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+128], r12
+ ; a[i+41] += m[41] * mu
+ mulx rcx, rax, QWORD PTR [r10+328]
+ mov r12, QWORD PTR [r9+144]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+136], r13
+ ; a[i+42] += m[42] * mu
+ mulx rcx, rax, QWORD PTR [r10+336]
+ mov r13, QWORD PTR [r9+152]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+144], r12
+ ; a[i+43] += m[43] * mu
+ mulx rcx, rax, QWORD PTR [r10+344]
+ mov r12, QWORD PTR [r9+160]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+152], r13
+ ; a[i+44] += m[44] * mu
+ mulx rcx, rax, QWORD PTR [r10+352]
+ mov r13, QWORD PTR [r9+168]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+160], r12
+ ; a[i+45] += m[45] * mu
+ mulx rcx, rax, QWORD PTR [r10+360]
+ mov r12, QWORD PTR [r9+176]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+168], r13
+ ; a[i+46] += m[46] * mu
+ mulx rcx, rax, QWORD PTR [r10+368]
+ mov r13, QWORD PTR [r9+184]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+176], r12
+ ; a[i+47] += m[47] * mu
+ mulx rcx, rax, QWORD PTR [r10+376]
+ mov r12, QWORD PTR [r9+192]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+184], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+192], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 1
+ add r9, 8
+ ; i -= 1
+ sub r11, 1
+ jnz L_3072_mont_loop_avx2_48
+ sub r9, 192
+ neg rbp
+ mov r8, r9
+ sub r9, 384
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+128]
+ mov rax, QWORD PTR [r8+128]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+120], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+136]
+ mov rcx, QWORD PTR [r8+136]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+128], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+144]
+ mov rdx, QWORD PTR [r8+144]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+136], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r8+152]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+144], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+160]
+ mov rcx, QWORD PTR [r8+160]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+152], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+168]
+ mov rdx, QWORD PTR [r8+168]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+160], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+176]
+ mov rax, QWORD PTR [r8+176]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+168], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+184]
+ mov rcx, QWORD PTR [r8+184]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+176], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+192]
+ mov rdx, QWORD PTR [r8+192]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+184], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [r8+200]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+192], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+208]
+ mov rcx, QWORD PTR [r8+208]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+200], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+216]
+ mov rdx, QWORD PTR [r8+216]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+208], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+224]
+ mov rax, QWORD PTR [r8+224]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+216], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+232]
+ mov rcx, QWORD PTR [r8+232]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+224], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+240]
+ mov rdx, QWORD PTR [r8+240]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+232], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [r8+248]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+240], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+256]
+ mov rcx, QWORD PTR [r8+256]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+248], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+264]
+ mov rdx, QWORD PTR [r8+264]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+256], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+272]
+ mov rax, QWORD PTR [r8+272]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+264], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+280]
+ mov rcx, QWORD PTR [r8+280]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+272], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+288]
+ mov rdx, QWORD PTR [r8+288]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+280], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [r8+296]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+288], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+304]
+ mov rcx, QWORD PTR [r8+304]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+296], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+312]
+ mov rdx, QWORD PTR [r8+312]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+304], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+320]
+ mov rax, QWORD PTR [r8+320]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+312], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+328]
+ mov rcx, QWORD PTR [r8+328]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+320], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+336]
+ mov rdx, QWORD PTR [r8+336]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+328], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [r8+344]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+336], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+352]
+ mov rcx, QWORD PTR [r8+352]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+344], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+360]
+ mov rdx, QWORD PTR [r8+360]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+352], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+368]
+ mov rax, QWORD PTR [r8+368]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+360], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+376]
+ mov rcx, QWORD PTR [r8+376]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+368], rax
+ sbb rcx, rdx
+ mov QWORD PTR [r9+376], rcx
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_3072_mont_reduce_avx2_48 ENDP
+_text ENDS
+ENDIF
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_add_24 PROC
+ sub rsp, 192
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ add r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ adc r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ adc r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ adc r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ adc r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ adc r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ adc r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ adc r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ adc r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ adc r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ adc r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ adc r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ adc r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ adc r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ adc r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ adc r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ adc r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ adc r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ adc r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ adc r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ adc r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ adc r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ adc r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ adc r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov QWORD PTR [rcx+184], r11
+ adc rax, 0
+ add rsp, 192
+ ret
+sp_3072_cond_add_24 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_cond_add_avx2_24 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ add r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ adc r12, r10
+ mov QWORD PTR [rcx+184], r12
+ adc rax, 0
+ pop r12
+ ret
+sp_3072_cond_add_avx2_24 ENDP
+_text ENDS
+ENDIF
+; /* Shift number left by n bit. (r = a << n)
+; *
+; * r Result of left shift by n.
+; * a Number to shift.
+; * n Amoutnt o shift.
+; */
+_text SEGMENT READONLY PARA
+sp_3072_lshift_48 PROC
+ push r12
+ push r13
+ mov r9, rcx
+ mov rcx, r8
+ mov r12, 0
+ mov r13, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [rdx+360]
+ mov r10, QWORD PTR [rdx+368]
+ mov r11, QWORD PTR [rdx+376]
+ shld r12, r11, cl
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+352], rax
+ mov QWORD PTR [r9+360], r8
+ mov QWORD PTR [r9+368], r10
+ mov QWORD PTR [r9+376], r11
+ mov QWORD PTR [r9+384], r12
+ mov r11, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [rdx+328]
+ mov r10, QWORD PTR [rdx+336]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+320], rax
+ mov QWORD PTR [r9+328], r8
+ mov QWORD PTR [r9+336], r10
+ mov QWORD PTR [r9+344], r13
+ mov r13, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [rdx+296]
+ mov r10, QWORD PTR [rdx+304]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+288], rax
+ mov QWORD PTR [r9+296], r8
+ mov QWORD PTR [r9+304], r10
+ mov QWORD PTR [r9+312], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [rdx+264]
+ mov r10, QWORD PTR [rdx+272]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+256], rax
+ mov QWORD PTR [r9+264], r8
+ mov QWORD PTR [r9+272], r10
+ mov QWORD PTR [r9+280], r13
+ mov r13, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rdx+232]
+ mov r10, QWORD PTR [rdx+240]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+224], rax
+ mov QWORD PTR [r9+232], r8
+ mov QWORD PTR [r9+240], r10
+ mov QWORD PTR [r9+248], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rdx+200]
+ mov r10, QWORD PTR [rdx+208]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+192], rax
+ mov QWORD PTR [r9+200], r8
+ mov QWORD PTR [r9+208], r10
+ mov QWORD PTR [r9+216], r13
+ mov r13, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov r10, QWORD PTR [rdx+176]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+160], rax
+ mov QWORD PTR [r9+168], r8
+ mov QWORD PTR [r9+176], r10
+ mov QWORD PTR [r9+184], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov r10, QWORD PTR [rdx+144]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+128], rax
+ mov QWORD PTR [r9+136], r8
+ mov QWORD PTR [r9+144], r10
+ mov QWORD PTR [r9+152], r13
+ mov r13, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+96], rax
+ mov QWORD PTR [r9+104], r8
+ mov QWORD PTR [r9+112], r10
+ mov QWORD PTR [r9+120], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+64], rax
+ mov QWORD PTR [r9+72], r8
+ mov QWORD PTR [r9+80], r10
+ mov QWORD PTR [r9+88], r13
+ mov r13, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+32], rax
+ mov QWORD PTR [r9+40], r8
+ mov QWORD PTR [r9+48], r10
+ mov QWORD PTR [r9+56], r11
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shl rax, cl
+ mov QWORD PTR [r9], rax
+ mov QWORD PTR [r9+8], r8
+ mov QWORD PTR [r9+16], r10
+ mov QWORD PTR [r9+24], r13
+ pop r13
+ pop r12
+ ret
+sp_3072_lshift_48 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFDEF WOLFSSL_SP_4096
+IFDEF WOLFSSL_SP_4096
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 512
+ xor r13, r13
+ jmp L_4096_from_bin_bswap_64_end
+L_4096_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_4096_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_4096_from_bin_bswap_64_start
+ jmp L_4096_from_bin_bswap_8_end
+L_4096_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_4096_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_4096_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_4096_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_4096_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_4096_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_4096_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_4096_from_bin_bswap_zero_end
+L_4096_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_4096_from_bin_bswap_zero_start
+L_4096_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_4096_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 512
+ xor r13, r13
+ jmp L_4096_from_bin_movbe_64_end
+L_4096_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_4096_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_4096_from_bin_movbe_64_start
+ jmp L_4096_from_bin_movbe_8_end
+L_4096_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_4096_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_4096_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_4096_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_4096_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_4096_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_4096_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_4096_from_bin_movbe_zero_end
+L_4096_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_4096_from_bin_movbe_zero_start
+L_4096_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_4096_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 512
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_to_bin_bswap PROC
+ mov rax, QWORD PTR [rcx+504]
+ mov r8, QWORD PTR [rcx+496]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ mov rax, QWORD PTR [rcx+488]
+ mov r8, QWORD PTR [rcx+480]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ mov rax, QWORD PTR [rcx+472]
+ mov r8, QWORD PTR [rcx+464]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ mov rax, QWORD PTR [rcx+456]
+ mov r8, QWORD PTR [rcx+448]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ mov rax, QWORD PTR [rcx+440]
+ mov r8, QWORD PTR [rcx+432]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ mov rax, QWORD PTR [rcx+424]
+ mov r8, QWORD PTR [rcx+416]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ mov rax, QWORD PTR [rcx+408]
+ mov r8, QWORD PTR [rcx+400]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ mov rax, QWORD PTR [rcx+392]
+ mov r8, QWORD PTR [rcx+384]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ mov rax, QWORD PTR [rcx+376]
+ mov r8, QWORD PTR [rcx+368]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ mov rax, QWORD PTR [rcx+360]
+ mov r8, QWORD PTR [rcx+352]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ mov rax, QWORD PTR [rcx+344]
+ mov r8, QWORD PTR [rcx+336]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ mov rax, QWORD PTR [rcx+328]
+ mov r8, QWORD PTR [rcx+320]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ mov rax, QWORD PTR [rcx+312]
+ mov r8, QWORD PTR [rcx+304]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ mov rax, QWORD PTR [rcx+296]
+ mov r8, QWORD PTR [rcx+288]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ mov rax, QWORD PTR [rcx+280]
+ mov r8, QWORD PTR [rcx+272]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ mov rax, QWORD PTR [rcx+264]
+ mov r8, QWORD PTR [rcx+256]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ mov rax, QWORD PTR [rcx+248]
+ mov r8, QWORD PTR [rcx+240]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+256], rax
+ mov QWORD PTR [rdx+264], r8
+ mov rax, QWORD PTR [rcx+232]
+ mov r8, QWORD PTR [rcx+224]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+272], rax
+ mov QWORD PTR [rdx+280], r8
+ mov rax, QWORD PTR [rcx+216]
+ mov r8, QWORD PTR [rcx+208]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+288], rax
+ mov QWORD PTR [rdx+296], r8
+ mov rax, QWORD PTR [rcx+200]
+ mov r8, QWORD PTR [rcx+192]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+304], rax
+ mov QWORD PTR [rdx+312], r8
+ mov rax, QWORD PTR [rcx+184]
+ mov r8, QWORD PTR [rcx+176]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+320], rax
+ mov QWORD PTR [rdx+328], r8
+ mov rax, QWORD PTR [rcx+168]
+ mov r8, QWORD PTR [rcx+160]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+336], rax
+ mov QWORD PTR [rdx+344], r8
+ mov rax, QWORD PTR [rcx+152]
+ mov r8, QWORD PTR [rcx+144]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+352], rax
+ mov QWORD PTR [rdx+360], r8
+ mov rax, QWORD PTR [rcx+136]
+ mov r8, QWORD PTR [rcx+128]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+368], rax
+ mov QWORD PTR [rdx+376], r8
+ mov rax, QWORD PTR [rcx+120]
+ mov r8, QWORD PTR [rcx+112]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+384], rax
+ mov QWORD PTR [rdx+392], r8
+ mov rax, QWORD PTR [rcx+104]
+ mov r8, QWORD PTR [rcx+96]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+400], rax
+ mov QWORD PTR [rdx+408], r8
+ mov rax, QWORD PTR [rcx+88]
+ mov r8, QWORD PTR [rcx+80]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+416], rax
+ mov QWORD PTR [rdx+424], r8
+ mov rax, QWORD PTR [rcx+72]
+ mov r8, QWORD PTR [rcx+64]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+432], rax
+ mov QWORD PTR [rdx+440], r8
+ mov rax, QWORD PTR [rcx+56]
+ mov r8, QWORD PTR [rcx+48]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+448], rax
+ mov QWORD PTR [rdx+456], r8
+ mov rax, QWORD PTR [rcx+40]
+ mov r8, QWORD PTR [rcx+32]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+464], rax
+ mov QWORD PTR [rdx+472], r8
+ mov rax, QWORD PTR [rcx+24]
+ mov r8, QWORD PTR [rcx+16]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+480], rax
+ mov QWORD PTR [rdx+488], r8
+ mov rax, QWORD PTR [rcx+8]
+ mov r8, QWORD PTR [rcx]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+496], rax
+ mov QWORD PTR [rdx+504], r8
+ ret
+sp_4096_to_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 512
+; * Uses the movbe instruction which is optional.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_to_bin_movbe PROC
+ movbe rax, QWORD PTR [rcx+504]
+ movbe r8, QWORD PTR [rcx+496]
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ movbe rax, QWORD PTR [rcx+488]
+ movbe r8, QWORD PTR [rcx+480]
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ movbe rax, QWORD PTR [rcx+472]
+ movbe r8, QWORD PTR [rcx+464]
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ movbe rax, QWORD PTR [rcx+456]
+ movbe r8, QWORD PTR [rcx+448]
+ mov QWORD PTR [rdx+48], rax
+ mov QWORD PTR [rdx+56], r8
+ movbe rax, QWORD PTR [rcx+440]
+ movbe r8, QWORD PTR [rcx+432]
+ mov QWORD PTR [rdx+64], rax
+ mov QWORD PTR [rdx+72], r8
+ movbe rax, QWORD PTR [rcx+424]
+ movbe r8, QWORD PTR [rcx+416]
+ mov QWORD PTR [rdx+80], rax
+ mov QWORD PTR [rdx+88], r8
+ movbe rax, QWORD PTR [rcx+408]
+ movbe r8, QWORD PTR [rcx+400]
+ mov QWORD PTR [rdx+96], rax
+ mov QWORD PTR [rdx+104], r8
+ movbe rax, QWORD PTR [rcx+392]
+ movbe r8, QWORD PTR [rcx+384]
+ mov QWORD PTR [rdx+112], rax
+ mov QWORD PTR [rdx+120], r8
+ movbe rax, QWORD PTR [rcx+376]
+ movbe r8, QWORD PTR [rcx+368]
+ mov QWORD PTR [rdx+128], rax
+ mov QWORD PTR [rdx+136], r8
+ movbe rax, QWORD PTR [rcx+360]
+ movbe r8, QWORD PTR [rcx+352]
+ mov QWORD PTR [rdx+144], rax
+ mov QWORD PTR [rdx+152], r8
+ movbe rax, QWORD PTR [rcx+344]
+ movbe r8, QWORD PTR [rcx+336]
+ mov QWORD PTR [rdx+160], rax
+ mov QWORD PTR [rdx+168], r8
+ movbe rax, QWORD PTR [rcx+328]
+ movbe r8, QWORD PTR [rcx+320]
+ mov QWORD PTR [rdx+176], rax
+ mov QWORD PTR [rdx+184], r8
+ movbe rax, QWORD PTR [rcx+312]
+ movbe r8, QWORD PTR [rcx+304]
+ mov QWORD PTR [rdx+192], rax
+ mov QWORD PTR [rdx+200], r8
+ movbe rax, QWORD PTR [rcx+296]
+ movbe r8, QWORD PTR [rcx+288]
+ mov QWORD PTR [rdx+208], rax
+ mov QWORD PTR [rdx+216], r8
+ movbe rax, QWORD PTR [rcx+280]
+ movbe r8, QWORD PTR [rcx+272]
+ mov QWORD PTR [rdx+224], rax
+ mov QWORD PTR [rdx+232], r8
+ movbe rax, QWORD PTR [rcx+264]
+ movbe r8, QWORD PTR [rcx+256]
+ mov QWORD PTR [rdx+240], rax
+ mov QWORD PTR [rdx+248], r8
+ movbe rax, QWORD PTR [rcx+248]
+ movbe r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rdx+256], rax
+ mov QWORD PTR [rdx+264], r8
+ movbe rax, QWORD PTR [rcx+232]
+ movbe r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rdx+272], rax
+ mov QWORD PTR [rdx+280], r8
+ movbe rax, QWORD PTR [rcx+216]
+ movbe r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rdx+288], rax
+ mov QWORD PTR [rdx+296], r8
+ movbe rax, QWORD PTR [rcx+200]
+ movbe r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rdx+304], rax
+ mov QWORD PTR [rdx+312], r8
+ movbe rax, QWORD PTR [rcx+184]
+ movbe r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rdx+320], rax
+ mov QWORD PTR [rdx+328], r8
+ movbe rax, QWORD PTR [rcx+168]
+ movbe r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rdx+336], rax
+ mov QWORD PTR [rdx+344], r8
+ movbe rax, QWORD PTR [rcx+152]
+ movbe r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rdx+352], rax
+ mov QWORD PTR [rdx+360], r8
+ movbe rax, QWORD PTR [rcx+136]
+ movbe r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rdx+368], rax
+ mov QWORD PTR [rdx+376], r8
+ movbe rax, QWORD PTR [rcx+120]
+ movbe r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rdx+384], rax
+ mov QWORD PTR [rdx+392], r8
+ movbe rax, QWORD PTR [rcx+104]
+ movbe r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rdx+400], rax
+ mov QWORD PTR [rdx+408], r8
+ movbe rax, QWORD PTR [rcx+88]
+ movbe r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rdx+416], rax
+ mov QWORD PTR [rdx+424], r8
+ movbe rax, QWORD PTR [rcx+72]
+ movbe r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rdx+432], rax
+ mov QWORD PTR [rdx+440], r8
+ movbe rax, QWORD PTR [rcx+56]
+ movbe r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rdx+448], rax
+ mov QWORD PTR [rdx+456], r8
+ movbe rax, QWORD PTR [rcx+40]
+ movbe r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rdx+464], rax
+ mov QWORD PTR [rdx+472], r8
+ movbe rax, QWORD PTR [rcx+24]
+ movbe r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rdx+480], rax
+ mov QWORD PTR [rdx+488], r8
+ movbe rax, QWORD PTR [rcx+8]
+ movbe r8, QWORD PTR [rcx]
+ mov QWORD PTR [rdx+496], rax
+ mov QWORD PTR [rdx+504], r8
+ ret
+sp_4096_to_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_sub_in_place_64 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rcx+128]
+ mov QWORD PTR [rcx+120], r9
+ sbb r8, QWORD PTR [rdx+128]
+ mov r9, QWORD PTR [rcx+136]
+ mov QWORD PTR [rcx+128], r8
+ sbb r9, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rcx+144]
+ mov QWORD PTR [rcx+136], r9
+ sbb r8, QWORD PTR [rdx+144]
+ mov r9, QWORD PTR [rcx+152]
+ mov QWORD PTR [rcx+144], r8
+ sbb r9, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rcx+160]
+ mov QWORD PTR [rcx+152], r9
+ sbb r8, QWORD PTR [rdx+160]
+ mov r9, QWORD PTR [rcx+168]
+ mov QWORD PTR [rcx+160], r8
+ sbb r9, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rcx+176]
+ mov QWORD PTR [rcx+168], r9
+ sbb r8, QWORD PTR [rdx+176]
+ mov r9, QWORD PTR [rcx+184]
+ mov QWORD PTR [rcx+176], r8
+ sbb r9, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rcx+192]
+ mov QWORD PTR [rcx+184], r9
+ sbb r8, QWORD PTR [rdx+192]
+ mov r9, QWORD PTR [rcx+200]
+ mov QWORD PTR [rcx+192], r8
+ sbb r9, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rcx+208]
+ mov QWORD PTR [rcx+200], r9
+ sbb r8, QWORD PTR [rdx+208]
+ mov r9, QWORD PTR [rcx+216]
+ mov QWORD PTR [rcx+208], r8
+ sbb r9, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rcx+224]
+ mov QWORD PTR [rcx+216], r9
+ sbb r8, QWORD PTR [rdx+224]
+ mov r9, QWORD PTR [rcx+232]
+ mov QWORD PTR [rcx+224], r8
+ sbb r9, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rcx+240]
+ mov QWORD PTR [rcx+232], r9
+ sbb r8, QWORD PTR [rdx+240]
+ mov r9, QWORD PTR [rcx+248]
+ mov QWORD PTR [rcx+240], r8
+ sbb r9, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rcx+256]
+ mov QWORD PTR [rcx+248], r9
+ sbb r8, QWORD PTR [rdx+256]
+ mov r9, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], r8
+ sbb r9, QWORD PTR [rdx+264]
+ mov r8, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r9
+ sbb r8, QWORD PTR [rdx+272]
+ mov r9, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], r8
+ sbb r9, QWORD PTR [rdx+280]
+ mov r8, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r9
+ sbb r8, QWORD PTR [rdx+288]
+ mov r9, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], r8
+ sbb r9, QWORD PTR [rdx+296]
+ mov r8, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r9
+ sbb r8, QWORD PTR [rdx+304]
+ mov r9, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], r8
+ sbb r9, QWORD PTR [rdx+312]
+ mov r8, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r9
+ sbb r8, QWORD PTR [rdx+320]
+ mov r9, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], r8
+ sbb r9, QWORD PTR [rdx+328]
+ mov r8, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r9
+ sbb r8, QWORD PTR [rdx+336]
+ mov r9, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], r8
+ sbb r9, QWORD PTR [rdx+344]
+ mov r8, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r9
+ sbb r8, QWORD PTR [rdx+352]
+ mov r9, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], r8
+ sbb r9, QWORD PTR [rdx+360]
+ mov r8, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r9
+ sbb r8, QWORD PTR [rdx+368]
+ mov r9, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], r8
+ sbb r9, QWORD PTR [rdx+376]
+ mov r8, QWORD PTR [rcx+384]
+ mov QWORD PTR [rcx+376], r9
+ sbb r8, QWORD PTR [rdx+384]
+ mov r9, QWORD PTR [rcx+392]
+ mov QWORD PTR [rcx+384], r8
+ sbb r9, QWORD PTR [rdx+392]
+ mov r8, QWORD PTR [rcx+400]
+ mov QWORD PTR [rcx+392], r9
+ sbb r8, QWORD PTR [rdx+400]
+ mov r9, QWORD PTR [rcx+408]
+ mov QWORD PTR [rcx+400], r8
+ sbb r9, QWORD PTR [rdx+408]
+ mov r8, QWORD PTR [rcx+416]
+ mov QWORD PTR [rcx+408], r9
+ sbb r8, QWORD PTR [rdx+416]
+ mov r9, QWORD PTR [rcx+424]
+ mov QWORD PTR [rcx+416], r8
+ sbb r9, QWORD PTR [rdx+424]
+ mov r8, QWORD PTR [rcx+432]
+ mov QWORD PTR [rcx+424], r9
+ sbb r8, QWORD PTR [rdx+432]
+ mov r9, QWORD PTR [rcx+440]
+ mov QWORD PTR [rcx+432], r8
+ sbb r9, QWORD PTR [rdx+440]
+ mov r8, QWORD PTR [rcx+448]
+ mov QWORD PTR [rcx+440], r9
+ sbb r8, QWORD PTR [rdx+448]
+ mov r9, QWORD PTR [rcx+456]
+ mov QWORD PTR [rcx+448], r8
+ sbb r9, QWORD PTR [rdx+456]
+ mov r8, QWORD PTR [rcx+464]
+ mov QWORD PTR [rcx+456], r9
+ sbb r8, QWORD PTR [rdx+464]
+ mov r9, QWORD PTR [rcx+472]
+ mov QWORD PTR [rcx+464], r8
+ sbb r9, QWORD PTR [rdx+472]
+ mov r8, QWORD PTR [rcx+480]
+ mov QWORD PTR [rcx+472], r9
+ sbb r8, QWORD PTR [rdx+480]
+ mov r9, QWORD PTR [rcx+488]
+ mov QWORD PTR [rcx+480], r8
+ sbb r9, QWORD PTR [rdx+488]
+ mov r8, QWORD PTR [rcx+496]
+ mov QWORD PTR [rcx+488], r9
+ sbb r8, QWORD PTR [rdx+496]
+ mov r9, QWORD PTR [rcx+504]
+ mov QWORD PTR [rcx+496], r8
+ sbb r9, QWORD PTR [rdx+504]
+ mov QWORD PTR [rcx+504], r9
+ sbb rax, 0
+ ret
+sp_4096_sub_in_place_64 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_add_64 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ adc r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ adc r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ adc r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ adc r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ adc r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ adc r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ adc r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ adc r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ adc r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ adc r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ adc r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ adc r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ adc r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ adc r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ adc r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ adc r10, QWORD PTR [r8+248]
+ mov r9, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+248], r10
+ adc r9, QWORD PTR [r8+256]
+ mov r10, QWORD PTR [rdx+264]
+ mov QWORD PTR [rcx+256], r9
+ adc r10, QWORD PTR [r8+264]
+ mov r9, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+264], r10
+ adc r9, QWORD PTR [r8+272]
+ mov r10, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+272], r9
+ adc r10, QWORD PTR [r8+280]
+ mov r9, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+280], r10
+ adc r9, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+288], r9
+ adc r10, QWORD PTR [r8+296]
+ mov r9, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+296], r10
+ adc r9, QWORD PTR [r8+304]
+ mov r10, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+304], r9
+ adc r10, QWORD PTR [r8+312]
+ mov r9, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+312], r10
+ adc r9, QWORD PTR [r8+320]
+ mov r10, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+320], r9
+ adc r10, QWORD PTR [r8+328]
+ mov r9, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+328], r10
+ adc r9, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+336], r9
+ adc r10, QWORD PTR [r8+344]
+ mov r9, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+344], r10
+ adc r9, QWORD PTR [r8+352]
+ mov r10, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+352], r9
+ adc r10, QWORD PTR [r8+360]
+ mov r9, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+360], r10
+ adc r9, QWORD PTR [r8+368]
+ mov r10, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+368], r9
+ adc r10, QWORD PTR [r8+376]
+ mov r9, QWORD PTR [rdx+384]
+ mov QWORD PTR [rcx+376], r10
+ adc r9, QWORD PTR [r8+384]
+ mov r10, QWORD PTR [rdx+392]
+ mov QWORD PTR [rcx+384], r9
+ adc r10, QWORD PTR [r8+392]
+ mov r9, QWORD PTR [rdx+400]
+ mov QWORD PTR [rcx+392], r10
+ adc r9, QWORD PTR [r8+400]
+ mov r10, QWORD PTR [rdx+408]
+ mov QWORD PTR [rcx+400], r9
+ adc r10, QWORD PTR [r8+408]
+ mov r9, QWORD PTR [rdx+416]
+ mov QWORD PTR [rcx+408], r10
+ adc r9, QWORD PTR [r8+416]
+ mov r10, QWORD PTR [rdx+424]
+ mov QWORD PTR [rcx+416], r9
+ adc r10, QWORD PTR [r8+424]
+ mov r9, QWORD PTR [rdx+432]
+ mov QWORD PTR [rcx+424], r10
+ adc r9, QWORD PTR [r8+432]
+ mov r10, QWORD PTR [rdx+440]
+ mov QWORD PTR [rcx+432], r9
+ adc r10, QWORD PTR [r8+440]
+ mov r9, QWORD PTR [rdx+448]
+ mov QWORD PTR [rcx+440], r10
+ adc r9, QWORD PTR [r8+448]
+ mov r10, QWORD PTR [rdx+456]
+ mov QWORD PTR [rcx+448], r9
+ adc r10, QWORD PTR [r8+456]
+ mov r9, QWORD PTR [rdx+464]
+ mov QWORD PTR [rcx+456], r10
+ adc r9, QWORD PTR [r8+464]
+ mov r10, QWORD PTR [rdx+472]
+ mov QWORD PTR [rcx+464], r9
+ adc r10, QWORD PTR [r8+472]
+ mov r9, QWORD PTR [rdx+480]
+ mov QWORD PTR [rcx+472], r10
+ adc r9, QWORD PTR [r8+480]
+ mov r10, QWORD PTR [rdx+488]
+ mov QWORD PTR [rcx+480], r9
+ adc r10, QWORD PTR [r8+488]
+ mov r9, QWORD PTR [rdx+496]
+ mov QWORD PTR [rcx+488], r10
+ adc r9, QWORD PTR [r8+496]
+ mov r10, QWORD PTR [rdx+504]
+ mov QWORD PTR [rcx+496], r9
+ adc r10, QWORD PTR [r8+504]
+ mov QWORD PTR [rcx+504], r10
+ adc rax, 0
+ ret
+sp_4096_add_64 ENDP
+_text ENDS
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mul_64 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 1576
+ mov QWORD PTR [rsp+1536], rcx
+ mov QWORD PTR [rsp+1544], rdx
+ mov QWORD PTR [rsp+1552], r8
+ lea r12, QWORD PTR [rsp+1024]
+ lea r14, QWORD PTR [rdx+256]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [r12+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [r12+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r12+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [r12+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [rdx+160]
+ mov QWORD PTR [r12+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r12+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [r12+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [r12+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r12+184], r10
+ adc rax, QWORD PTR [r14+192]
+ mov r9, QWORD PTR [rdx+200]
+ mov QWORD PTR [r12+192], rax
+ adc r9, QWORD PTR [r14+200]
+ mov r10, QWORD PTR [rdx+208]
+ mov QWORD PTR [r12+200], r9
+ adc r10, QWORD PTR [r14+208]
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [r12+208], r10
+ adc rax, QWORD PTR [r14+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [r12+216], rax
+ adc r9, QWORD PTR [r14+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [r12+224], r9
+ adc r10, QWORD PTR [r14+232]
+ mov rax, QWORD PTR [rdx+240]
+ mov QWORD PTR [r12+232], r10
+ adc rax, QWORD PTR [r14+240]
+ mov r9, QWORD PTR [rdx+248]
+ mov QWORD PTR [r12+240], rax
+ adc r9, QWORD PTR [r14+248]
+ mov QWORD PTR [r12+248], r9
+ adc r15, 0
+ mov QWORD PTR [rsp+1560], r15
+ lea r13, QWORD PTR [rsp+1280]
+ lea r14, QWORD PTR [r8+256]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [r8+128]
+ mov QWORD PTR [r13+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [r8+136]
+ mov QWORD PTR [r13+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [r8+144]
+ mov QWORD PTR [r13+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [r8+152]
+ mov QWORD PTR [r13+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [r8+160]
+ mov QWORD PTR [r13+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [r8+168]
+ mov QWORD PTR [r13+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [r8+176]
+ mov QWORD PTR [r13+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [r8+184]
+ mov QWORD PTR [r13+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov rax, QWORD PTR [r8+192]
+ mov QWORD PTR [r13+184], r10
+ adc rax, QWORD PTR [r14+192]
+ mov r9, QWORD PTR [r8+200]
+ mov QWORD PTR [r13+192], rax
+ adc r9, QWORD PTR [r14+200]
+ mov r10, QWORD PTR [r8+208]
+ mov QWORD PTR [r13+200], r9
+ adc r10, QWORD PTR [r14+208]
+ mov rax, QWORD PTR [r8+216]
+ mov QWORD PTR [r13+208], r10
+ adc rax, QWORD PTR [r14+216]
+ mov r9, QWORD PTR [r8+224]
+ mov QWORD PTR [r13+216], rax
+ adc r9, QWORD PTR [r14+224]
+ mov r10, QWORD PTR [r8+232]
+ mov QWORD PTR [r13+224], r9
+ adc r10, QWORD PTR [r14+232]
+ mov rax, QWORD PTR [r8+240]
+ mov QWORD PTR [r13+232], r10
+ adc rax, QWORD PTR [r14+240]
+ mov r9, QWORD PTR [r8+248]
+ mov QWORD PTR [r13+240], rax
+ adc r9, QWORD PTR [r14+248]
+ mov QWORD PTR [r13+248], r9
+ adc rdi, 0
+ mov QWORD PTR [rsp+1568], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_2048_mul_32
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ lea rcx, QWORD PTR [rsp+512]
+ add r8, 256
+ add rdx, 256
+ call sp_2048_mul_32
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ mov rcx, QWORD PTR [rsp+1536]
+ call sp_2048_mul_32
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ mov rcx, QWORD PTR [rsp+1536]
+ENDIF
+ mov r15, QWORD PTR [rsp+1560]
+ mov rdi, QWORD PTR [rsp+1568]
+ mov rsi, QWORD PTR [rsp+1536]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+1024]
+ lea r13, QWORD PTR [rsp+1280]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 512
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12], rax
+ mov QWORD PTR [r13], r9
+ mov rax, QWORD PTR [r12+8]
+ mov r9, QWORD PTR [r13+8]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+8], rax
+ mov QWORD PTR [r13+8], r9
+ mov rax, QWORD PTR [r12+16]
+ mov r9, QWORD PTR [r13+16]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+16], rax
+ mov QWORD PTR [r13+16], r9
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+24], rax
+ mov QWORD PTR [r13+24], r9
+ mov rax, QWORD PTR [r12+32]
+ mov r9, QWORD PTR [r13+32]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+32], rax
+ mov QWORD PTR [r13+32], r9
+ mov rax, QWORD PTR [r12+40]
+ mov r9, QWORD PTR [r13+40]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+40], rax
+ mov QWORD PTR [r13+40], r9
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+48], rax
+ mov QWORD PTR [r13+48], r9
+ mov rax, QWORD PTR [r12+56]
+ mov r9, QWORD PTR [r13+56]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+56], rax
+ mov QWORD PTR [r13+56], r9
+ mov rax, QWORD PTR [r12+64]
+ mov r9, QWORD PTR [r13+64]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+64], rax
+ mov QWORD PTR [r13+64], r9
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+72], rax
+ mov QWORD PTR [r13+72], r9
+ mov rax, QWORD PTR [r12+80]
+ mov r9, QWORD PTR [r13+80]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+80], rax
+ mov QWORD PTR [r13+80], r9
+ mov rax, QWORD PTR [r12+88]
+ mov r9, QWORD PTR [r13+88]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+88], rax
+ mov QWORD PTR [r13+88], r9
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+96], rax
+ mov QWORD PTR [r13+96], r9
+ mov rax, QWORD PTR [r12+104]
+ mov r9, QWORD PTR [r13+104]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+104], rax
+ mov QWORD PTR [r13+104], r9
+ mov rax, QWORD PTR [r12+112]
+ mov r9, QWORD PTR [r13+112]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+112], rax
+ mov QWORD PTR [r13+112], r9
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+120], rax
+ mov QWORD PTR [r13+120], r9
+ mov rax, QWORD PTR [r12+128]
+ mov r9, QWORD PTR [r13+128]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+128], rax
+ mov QWORD PTR [r13+128], r9
+ mov rax, QWORD PTR [r12+136]
+ mov r9, QWORD PTR [r13+136]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+136], rax
+ mov QWORD PTR [r13+136], r9
+ mov rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [r13+144]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+144], rax
+ mov QWORD PTR [r13+144], r9
+ mov rax, QWORD PTR [r12+152]
+ mov r9, QWORD PTR [r13+152]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+152], rax
+ mov QWORD PTR [r13+152], r9
+ mov rax, QWORD PTR [r12+160]
+ mov r9, QWORD PTR [r13+160]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+160], rax
+ mov QWORD PTR [r13+160], r9
+ mov rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [r13+168]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+168], rax
+ mov QWORD PTR [r13+168], r9
+ mov rax, QWORD PTR [r12+176]
+ mov r9, QWORD PTR [r13+176]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+176], rax
+ mov QWORD PTR [r13+176], r9
+ mov rax, QWORD PTR [r12+184]
+ mov r9, QWORD PTR [r13+184]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+184], rax
+ mov QWORD PTR [r13+184], r9
+ mov rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [r13+192]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+192], rax
+ mov QWORD PTR [r13+192], r9
+ mov rax, QWORD PTR [r12+200]
+ mov r9, QWORD PTR [r13+200]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+200], rax
+ mov QWORD PTR [r13+200], r9
+ mov rax, QWORD PTR [r12+208]
+ mov r9, QWORD PTR [r13+208]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+208], rax
+ mov QWORD PTR [r13+208], r9
+ mov rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [r13+216]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+216], rax
+ mov QWORD PTR [r13+216], r9
+ mov rax, QWORD PTR [r12+224]
+ mov r9, QWORD PTR [r13+224]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+224], rax
+ mov QWORD PTR [r13+224], r9
+ mov rax, QWORD PTR [r12+232]
+ mov r9, QWORD PTR [r13+232]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+232], rax
+ mov QWORD PTR [r13+232], r9
+ mov rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [r13+240]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+240], rax
+ mov QWORD PTR [r13+240], r9
+ mov rax, QWORD PTR [r12+248]
+ mov r9, QWORD PTR [r13+248]
+ and rax, rdi
+ and r9, r15
+ mov QWORD PTR [r12+248], rax
+ mov QWORD PTR [r13+248], r9
+ mov rax, QWORD PTR [r12]
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r13+248]
+ mov QWORD PTR [rsi+248], r9
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+512]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [r13+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [r13+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [r13+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [r13+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [r13+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [r13+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [r13+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [r13+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [r13+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [r13+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [r13+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [r13+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [r13+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [r13+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [r13+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [r13+376]
+ mov rax, QWORD PTR [r12+384]
+ mov QWORD PTR [r12+376], r10
+ sbb rax, QWORD PTR [r13+384]
+ mov r9, QWORD PTR [r12+392]
+ mov QWORD PTR [r12+384], rax
+ sbb r9, QWORD PTR [r13+392]
+ mov r10, QWORD PTR [r12+400]
+ mov QWORD PTR [r12+392], r9
+ sbb r10, QWORD PTR [r13+400]
+ mov rax, QWORD PTR [r12+408]
+ mov QWORD PTR [r12+400], r10
+ sbb rax, QWORD PTR [r13+408]
+ mov r9, QWORD PTR [r12+416]
+ mov QWORD PTR [r12+408], rax
+ sbb r9, QWORD PTR [r13+416]
+ mov r10, QWORD PTR [r12+424]
+ mov QWORD PTR [r12+416], r9
+ sbb r10, QWORD PTR [r13+424]
+ mov rax, QWORD PTR [r12+432]
+ mov QWORD PTR [r12+424], r10
+ sbb rax, QWORD PTR [r13+432]
+ mov r9, QWORD PTR [r12+440]
+ mov QWORD PTR [r12+432], rax
+ sbb r9, QWORD PTR [r13+440]
+ mov r10, QWORD PTR [r12+448]
+ mov QWORD PTR [r12+440], r9
+ sbb r10, QWORD PTR [r13+448]
+ mov rax, QWORD PTR [r12+456]
+ mov QWORD PTR [r12+448], r10
+ sbb rax, QWORD PTR [r13+456]
+ mov r9, QWORD PTR [r12+464]
+ mov QWORD PTR [r12+456], rax
+ sbb r9, QWORD PTR [r13+464]
+ mov r10, QWORD PTR [r12+472]
+ mov QWORD PTR [r12+464], r9
+ sbb r10, QWORD PTR [r13+472]
+ mov rax, QWORD PTR [r12+480]
+ mov QWORD PTR [r12+472], r10
+ sbb rax, QWORD PTR [r13+480]
+ mov r9, QWORD PTR [r12+488]
+ mov QWORD PTR [r12+480], rax
+ sbb r9, QWORD PTR [r13+488]
+ mov r10, QWORD PTR [r12+496]
+ mov QWORD PTR [r12+488], r9
+ sbb r10, QWORD PTR [r13+496]
+ mov rax, QWORD PTR [r12+504]
+ mov QWORD PTR [r12+496], r10
+ sbb rax, QWORD PTR [r13+504]
+ mov QWORD PTR [r12+504], rax
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [rcx+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [rcx+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [rcx+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [rcx+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [rcx+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [rcx+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [rcx+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [rcx+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [rcx+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [rcx+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [rcx+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [rcx+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [rcx+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [rcx+376]
+ mov rax, QWORD PTR [r12+384]
+ mov QWORD PTR [r12+376], r10
+ sbb rax, QWORD PTR [rcx+384]
+ mov r9, QWORD PTR [r12+392]
+ mov QWORD PTR [r12+384], rax
+ sbb r9, QWORD PTR [rcx+392]
+ mov r10, QWORD PTR [r12+400]
+ mov QWORD PTR [r12+392], r9
+ sbb r10, QWORD PTR [rcx+400]
+ mov rax, QWORD PTR [r12+408]
+ mov QWORD PTR [r12+400], r10
+ sbb rax, QWORD PTR [rcx+408]
+ mov r9, QWORD PTR [r12+416]
+ mov QWORD PTR [r12+408], rax
+ sbb r9, QWORD PTR [rcx+416]
+ mov r10, QWORD PTR [r12+424]
+ mov QWORD PTR [r12+416], r9
+ sbb r10, QWORD PTR [rcx+424]
+ mov rax, QWORD PTR [r12+432]
+ mov QWORD PTR [r12+424], r10
+ sbb rax, QWORD PTR [rcx+432]
+ mov r9, QWORD PTR [r12+440]
+ mov QWORD PTR [r12+432], rax
+ sbb r9, QWORD PTR [rcx+440]
+ mov r10, QWORD PTR [r12+448]
+ mov QWORD PTR [r12+440], r9
+ sbb r10, QWORD PTR [rcx+448]
+ mov rax, QWORD PTR [r12+456]
+ mov QWORD PTR [r12+448], r10
+ sbb rax, QWORD PTR [rcx+456]
+ mov r9, QWORD PTR [r12+464]
+ mov QWORD PTR [r12+456], rax
+ sbb r9, QWORD PTR [rcx+464]
+ mov r10, QWORD PTR [r12+472]
+ mov QWORD PTR [r12+464], r9
+ sbb r10, QWORD PTR [rcx+472]
+ mov rax, QWORD PTR [r12+480]
+ mov QWORD PTR [r12+472], r10
+ sbb rax, QWORD PTR [rcx+480]
+ mov r9, QWORD PTR [r12+488]
+ mov QWORD PTR [r12+480], rax
+ sbb r9, QWORD PTR [rcx+488]
+ mov r10, QWORD PTR [r12+496]
+ mov QWORD PTR [r12+488], r9
+ sbb r10, QWORD PTR [rcx+496]
+ mov rax, QWORD PTR [r12+504]
+ mov QWORD PTR [r12+496], r10
+ sbb rax, QWORD PTR [rcx+504]
+ mov QWORD PTR [r12+504], rax
+ sbb r11, 0
+ sub rsi, 256
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r12+256]
+ mov rax, QWORD PTR [rsi+264]
+ mov QWORD PTR [rsi+256], r10
+ adc rax, QWORD PTR [r12+264]
+ mov r9, QWORD PTR [rsi+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, QWORD PTR [r12+272]
+ mov r10, QWORD PTR [rsi+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, QWORD PTR [r12+280]
+ mov rax, QWORD PTR [rsi+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, QWORD PTR [r12+288]
+ mov r9, QWORD PTR [rsi+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, QWORD PTR [r12+296]
+ mov r10, QWORD PTR [rsi+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, QWORD PTR [r12+304]
+ mov rax, QWORD PTR [rsi+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, QWORD PTR [r12+312]
+ mov r9, QWORD PTR [rsi+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, QWORD PTR [r12+320]
+ mov r10, QWORD PTR [rsi+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, QWORD PTR [r12+328]
+ mov rax, QWORD PTR [rsi+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, QWORD PTR [r12+336]
+ mov r9, QWORD PTR [rsi+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, QWORD PTR [r12+344]
+ mov r10, QWORD PTR [rsi+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, QWORD PTR [r12+352]
+ mov rax, QWORD PTR [rsi+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, QWORD PTR [r12+360]
+ mov r9, QWORD PTR [rsi+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, QWORD PTR [r12+368]
+ mov r10, QWORD PTR [rsi+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, QWORD PTR [r12+376]
+ mov rax, QWORD PTR [rsi+384]
+ mov QWORD PTR [rsi+376], r10
+ adc rax, QWORD PTR [r12+384]
+ mov r9, QWORD PTR [rsi+392]
+ mov QWORD PTR [rsi+384], rax
+ adc r9, QWORD PTR [r12+392]
+ mov r10, QWORD PTR [rsi+400]
+ mov QWORD PTR [rsi+392], r9
+ adc r10, QWORD PTR [r12+400]
+ mov rax, QWORD PTR [rsi+408]
+ mov QWORD PTR [rsi+400], r10
+ adc rax, QWORD PTR [r12+408]
+ mov r9, QWORD PTR [rsi+416]
+ mov QWORD PTR [rsi+408], rax
+ adc r9, QWORD PTR [r12+416]
+ mov r10, QWORD PTR [rsi+424]
+ mov QWORD PTR [rsi+416], r9
+ adc r10, QWORD PTR [r12+424]
+ mov rax, QWORD PTR [rsi+432]
+ mov QWORD PTR [rsi+424], r10
+ adc rax, QWORD PTR [r12+432]
+ mov r9, QWORD PTR [rsi+440]
+ mov QWORD PTR [rsi+432], rax
+ adc r9, QWORD PTR [r12+440]
+ mov r10, QWORD PTR [rsi+448]
+ mov QWORD PTR [rsi+440], r9
+ adc r10, QWORD PTR [r12+448]
+ mov rax, QWORD PTR [rsi+456]
+ mov QWORD PTR [rsi+448], r10
+ adc rax, QWORD PTR [r12+456]
+ mov r9, QWORD PTR [rsi+464]
+ mov QWORD PTR [rsi+456], rax
+ adc r9, QWORD PTR [r12+464]
+ mov r10, QWORD PTR [rsi+472]
+ mov QWORD PTR [rsi+464], r9
+ adc r10, QWORD PTR [r12+472]
+ mov rax, QWORD PTR [rsi+480]
+ mov QWORD PTR [rsi+472], r10
+ adc rax, QWORD PTR [r12+480]
+ mov r9, QWORD PTR [rsi+488]
+ mov QWORD PTR [rsi+480], rax
+ adc r9, QWORD PTR [r12+488]
+ mov r10, QWORD PTR [rsi+496]
+ mov QWORD PTR [rsi+488], r9
+ adc r10, QWORD PTR [r12+496]
+ mov rax, QWORD PTR [rsi+504]
+ mov QWORD PTR [rsi+496], r10
+ adc rax, QWORD PTR [r12+504]
+ mov QWORD PTR [rsi+504], rax
+ adc r11, 0
+ mov QWORD PTR [rcx+768], r11
+ add rsi, 256
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ xor r11, r11
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r13+256]
+ mov QWORD PTR [rsi+256], r10
+ adc r11, 0
+ ; Add to zero
+ mov rax, QWORD PTR [r13+264]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+384]
+ mov QWORD PTR [rsi+376], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+392]
+ mov QWORD PTR [rsi+384], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+400]
+ mov QWORD PTR [rsi+392], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+408]
+ mov QWORD PTR [rsi+400], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+416]
+ mov QWORD PTR [rsi+408], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+424]
+ mov QWORD PTR [rsi+416], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+432]
+ mov QWORD PTR [rsi+424], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+440]
+ mov QWORD PTR [rsi+432], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+448]
+ mov QWORD PTR [rsi+440], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+456]
+ mov QWORD PTR [rsi+448], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+464]
+ mov QWORD PTR [rsi+456], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+472]
+ mov QWORD PTR [rsi+464], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+480]
+ mov QWORD PTR [rsi+472], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+488]
+ mov QWORD PTR [rsi+480], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+496]
+ mov QWORD PTR [rsi+488], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+504]
+ mov QWORD PTR [rsi+496], r10
+ adc rax, 0
+ mov QWORD PTR [rsi+504], rax
+ add rsp, 1576
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_4096_mul_64 ENDP
+_text ENDS
+; /* Add a to a into r. (r = a + a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_2048_dbl_32 PROC
+ mov r8, QWORD PTR [rdx]
+ xor rax, rax
+ add r8, r8
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r8
+ adc r9, r9
+ mov QWORD PTR [rcx+248], r9
+ adc rax, 0
+ ret
+sp_2048_dbl_32 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_sqr_64 PROC
+ push r12
+ sub rsp, 1304
+ mov QWORD PTR [rsp+1280], rcx
+ mov QWORD PTR [rsp+1288], rdx
+ lea r10, QWORD PTR [rsp+1024]
+ lea r11, QWORD PTR [rdx+256]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [r10+120], r8
+ adc rax, QWORD PTR [r11+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov QWORD PTR [r10+128], rax
+ adc r8, QWORD PTR [r11+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r10+136], r8
+ adc rax, QWORD PTR [r11+144]
+ mov r8, QWORD PTR [rdx+152]
+ mov QWORD PTR [r10+144], rax
+ adc r8, QWORD PTR [r11+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov QWORD PTR [r10+152], r8
+ adc rax, QWORD PTR [r11+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov QWORD PTR [r10+160], rax
+ adc r8, QWORD PTR [r11+168]
+ mov rax, QWORD PTR [rdx+176]
+ mov QWORD PTR [r10+168], r8
+ adc rax, QWORD PTR [r11+176]
+ mov r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+176], rax
+ adc r8, QWORD PTR [r11+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r10+184], r8
+ adc rax, QWORD PTR [r11+192]
+ mov r8, QWORD PTR [rdx+200]
+ mov QWORD PTR [r10+192], rax
+ adc r8, QWORD PTR [r11+200]
+ mov rax, QWORD PTR [rdx+208]
+ mov QWORD PTR [r10+200], r8
+ adc rax, QWORD PTR [r11+208]
+ mov r8, QWORD PTR [rdx+216]
+ mov QWORD PTR [r10+208], rax
+ adc r8, QWORD PTR [r11+216]
+ mov rax, QWORD PTR [rdx+224]
+ mov QWORD PTR [r10+216], r8
+ adc rax, QWORD PTR [r11+224]
+ mov r8, QWORD PTR [rdx+232]
+ mov QWORD PTR [r10+224], rax
+ adc r8, QWORD PTR [r11+232]
+ mov rax, QWORD PTR [rdx+240]
+ mov QWORD PTR [r10+232], r8
+ adc rax, QWORD PTR [r11+240]
+ mov r8, QWORD PTR [rdx+248]
+ mov QWORD PTR [r10+240], rax
+ adc r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r10+248], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+1296], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_2048_sqr_32
+ mov rdx, QWORD PTR [rsp+1288]
+ lea rcx, QWORD PTR [rsp+512]
+ add rdx, 256
+ call sp_2048_sqr_32
+ mov rdx, QWORD PTR [rsp+1288]
+ mov rcx, QWORD PTR [rsp+1280]
+ call sp_2048_sqr_32
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+1288]
+ mov rcx, QWORD PTR [rsp+1280]
+ENDIF
+ mov r12, QWORD PTR [rsp+1296]
+ lea r10, QWORD PTR [rsp+1024]
+ mov r9, r12
+ neg r12
+ mov rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [r10+8]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+512], rax
+ mov QWORD PTR [rcx+520], r8
+ mov rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [r10+24]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+528], rax
+ mov QWORD PTR [rcx+536], r8
+ mov rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [r10+40]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+544], rax
+ mov QWORD PTR [rcx+552], r8
+ mov rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [r10+56]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+560], rax
+ mov QWORD PTR [rcx+568], r8
+ mov rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [r10+72]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+576], rax
+ mov QWORD PTR [rcx+584], r8
+ mov rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [r10+88]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+592], rax
+ mov QWORD PTR [rcx+600], r8
+ mov rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [r10+104]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+608], rax
+ mov QWORD PTR [rcx+616], r8
+ mov rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [r10+120]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+624], rax
+ mov QWORD PTR [rcx+632], r8
+ mov rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [r10+136]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+640], rax
+ mov QWORD PTR [rcx+648], r8
+ mov rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [r10+152]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+656], rax
+ mov QWORD PTR [rcx+664], r8
+ mov rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [r10+168]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+672], rax
+ mov QWORD PTR [rcx+680], r8
+ mov rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [r10+184]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+688], rax
+ mov QWORD PTR [rcx+696], r8
+ mov rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [r10+200]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+704], rax
+ mov QWORD PTR [rcx+712], r8
+ mov rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [r10+216]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+720], rax
+ mov QWORD PTR [rcx+728], r8
+ mov rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [r10+232]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+736], rax
+ mov QWORD PTR [rcx+744], r8
+ mov rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [r10+248]
+ and rax, r12
+ and r8, r12
+ mov QWORD PTR [rcx+752], rax
+ mov QWORD PTR [rcx+760], r8
+ mov rax, QWORD PTR [rcx+512]
+ add rax, rax
+ mov r8, QWORD PTR [rcx+520]
+ mov QWORD PTR [rcx+512], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+528]
+ mov QWORD PTR [rcx+520], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+536]
+ mov QWORD PTR [rcx+528], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+544]
+ mov QWORD PTR [rcx+536], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+552]
+ mov QWORD PTR [rcx+544], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+560]
+ mov QWORD PTR [rcx+552], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+568]
+ mov QWORD PTR [rcx+560], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+576]
+ mov QWORD PTR [rcx+568], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+584]
+ mov QWORD PTR [rcx+576], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+592]
+ mov QWORD PTR [rcx+584], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+600]
+ mov QWORD PTR [rcx+592], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+608]
+ mov QWORD PTR [rcx+600], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+616]
+ mov QWORD PTR [rcx+608], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+624]
+ mov QWORD PTR [rcx+616], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+632]
+ mov QWORD PTR [rcx+624], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+640]
+ mov QWORD PTR [rcx+632], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+648]
+ mov QWORD PTR [rcx+640], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+656]
+ mov QWORD PTR [rcx+648], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+664]
+ mov QWORD PTR [rcx+656], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+672]
+ mov QWORD PTR [rcx+664], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+680]
+ mov QWORD PTR [rcx+672], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+688]
+ mov QWORD PTR [rcx+680], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+696]
+ mov QWORD PTR [rcx+688], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+704]
+ mov QWORD PTR [rcx+696], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+712]
+ mov QWORD PTR [rcx+704], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+720]
+ mov QWORD PTR [rcx+712], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+728]
+ mov QWORD PTR [rcx+720], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+736]
+ mov QWORD PTR [rcx+728], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+744]
+ mov QWORD PTR [rcx+736], rax
+ adc r8, r8
+ mov rax, QWORD PTR [rcx+752]
+ mov QWORD PTR [rcx+744], r8
+ adc rax, rax
+ mov r8, QWORD PTR [rcx+760]
+ mov QWORD PTR [rcx+752], rax
+ adc r8, r8
+ mov QWORD PTR [rcx+760], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+512]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rdx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rdx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rdx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rdx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rdx+376]
+ mov rax, QWORD PTR [r10+384]
+ mov QWORD PTR [r10+376], r8
+ sbb rax, QWORD PTR [rdx+384]
+ mov r8, QWORD PTR [r10+392]
+ mov QWORD PTR [r10+384], rax
+ sbb r8, QWORD PTR [rdx+392]
+ mov rax, QWORD PTR [r10+400]
+ mov QWORD PTR [r10+392], r8
+ sbb rax, QWORD PTR [rdx+400]
+ mov r8, QWORD PTR [r10+408]
+ mov QWORD PTR [r10+400], rax
+ sbb r8, QWORD PTR [rdx+408]
+ mov rax, QWORD PTR [r10+416]
+ mov QWORD PTR [r10+408], r8
+ sbb rax, QWORD PTR [rdx+416]
+ mov r8, QWORD PTR [r10+424]
+ mov QWORD PTR [r10+416], rax
+ sbb r8, QWORD PTR [rdx+424]
+ mov rax, QWORD PTR [r10+432]
+ mov QWORD PTR [r10+424], r8
+ sbb rax, QWORD PTR [rdx+432]
+ mov r8, QWORD PTR [r10+440]
+ mov QWORD PTR [r10+432], rax
+ sbb r8, QWORD PTR [rdx+440]
+ mov rax, QWORD PTR [r10+448]
+ mov QWORD PTR [r10+440], r8
+ sbb rax, QWORD PTR [rdx+448]
+ mov r8, QWORD PTR [r10+456]
+ mov QWORD PTR [r10+448], rax
+ sbb r8, QWORD PTR [rdx+456]
+ mov rax, QWORD PTR [r10+464]
+ mov QWORD PTR [r10+456], r8
+ sbb rax, QWORD PTR [rdx+464]
+ mov r8, QWORD PTR [r10+472]
+ mov QWORD PTR [r10+464], rax
+ sbb r8, QWORD PTR [rdx+472]
+ mov rax, QWORD PTR [r10+480]
+ mov QWORD PTR [r10+472], r8
+ sbb rax, QWORD PTR [rdx+480]
+ mov r8, QWORD PTR [r10+488]
+ mov QWORD PTR [r10+480], rax
+ sbb r8, QWORD PTR [rdx+488]
+ mov rax, QWORD PTR [r10+496]
+ mov QWORD PTR [r10+488], r8
+ sbb rax, QWORD PTR [rdx+496]
+ mov r8, QWORD PTR [r10+504]
+ mov QWORD PTR [r10+496], rax
+ sbb r8, QWORD PTR [rdx+504]
+ mov QWORD PTR [r10+504], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rcx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rcx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rcx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rcx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rcx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rcx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rcx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rcx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rcx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rcx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rcx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rcx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rcx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rcx+376]
+ mov rax, QWORD PTR [r10+384]
+ mov QWORD PTR [r10+376], r8
+ sbb rax, QWORD PTR [rcx+384]
+ mov r8, QWORD PTR [r10+392]
+ mov QWORD PTR [r10+384], rax
+ sbb r8, QWORD PTR [rcx+392]
+ mov rax, QWORD PTR [r10+400]
+ mov QWORD PTR [r10+392], r8
+ sbb rax, QWORD PTR [rcx+400]
+ mov r8, QWORD PTR [r10+408]
+ mov QWORD PTR [r10+400], rax
+ sbb r8, QWORD PTR [rcx+408]
+ mov rax, QWORD PTR [r10+416]
+ mov QWORD PTR [r10+408], r8
+ sbb rax, QWORD PTR [rcx+416]
+ mov r8, QWORD PTR [r10+424]
+ mov QWORD PTR [r10+416], rax
+ sbb r8, QWORD PTR [rcx+424]
+ mov rax, QWORD PTR [r10+432]
+ mov QWORD PTR [r10+424], r8
+ sbb rax, QWORD PTR [rcx+432]
+ mov r8, QWORD PTR [r10+440]
+ mov QWORD PTR [r10+432], rax
+ sbb r8, QWORD PTR [rcx+440]
+ mov rax, QWORD PTR [r10+448]
+ mov QWORD PTR [r10+440], r8
+ sbb rax, QWORD PTR [rcx+448]
+ mov r8, QWORD PTR [r10+456]
+ mov QWORD PTR [r10+448], rax
+ sbb r8, QWORD PTR [rcx+456]
+ mov rax, QWORD PTR [r10+464]
+ mov QWORD PTR [r10+456], r8
+ sbb rax, QWORD PTR [rcx+464]
+ mov r8, QWORD PTR [r10+472]
+ mov QWORD PTR [r10+464], rax
+ sbb r8, QWORD PTR [rcx+472]
+ mov rax, QWORD PTR [r10+480]
+ mov QWORD PTR [r10+472], r8
+ sbb rax, QWORD PTR [rcx+480]
+ mov r8, QWORD PTR [r10+488]
+ mov QWORD PTR [r10+480], rax
+ sbb r8, QWORD PTR [rcx+488]
+ mov rax, QWORD PTR [r10+496]
+ mov QWORD PTR [r10+488], r8
+ sbb rax, QWORD PTR [rcx+496]
+ mov r8, QWORD PTR [r10+504]
+ mov QWORD PTR [r10+496], rax
+ sbb r8, QWORD PTR [rcx+504]
+ mov QWORD PTR [r10+504], r8
+ sbb r9, 0
+ ; Add in place
+ mov rax, QWORD PTR [rcx+256]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [rcx+384]
+ mov QWORD PTR [rcx+376], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [rcx+392]
+ mov QWORD PTR [rcx+384], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [rcx+400]
+ mov QWORD PTR [rcx+392], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [rcx+408]
+ mov QWORD PTR [rcx+400], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [rcx+416]
+ mov QWORD PTR [rcx+408], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [rcx+424]
+ mov QWORD PTR [rcx+416], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [rcx+432]
+ mov QWORD PTR [rcx+424], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [rcx+440]
+ mov QWORD PTR [rcx+432], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [rcx+448]
+ mov QWORD PTR [rcx+440], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [rcx+456]
+ mov QWORD PTR [rcx+448], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [rcx+464]
+ mov QWORD PTR [rcx+456], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [rcx+472]
+ mov QWORD PTR [rcx+464], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [rcx+480]
+ mov QWORD PTR [rcx+472], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [rcx+488]
+ mov QWORD PTR [rcx+480], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [rcx+496]
+ mov QWORD PTR [rcx+488], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [rcx+504]
+ mov QWORD PTR [rcx+496], rax
+ adc r8, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [rcx+512]
+ mov QWORD PTR [rcx+504], r8
+ adc rax, QWORD PTR [r10+256]
+ mov r8, QWORD PTR [rcx+520]
+ mov QWORD PTR [rcx+512], rax
+ adc r8, QWORD PTR [r10+264]
+ mov rax, QWORD PTR [rcx+528]
+ mov QWORD PTR [rcx+520], r8
+ adc rax, QWORD PTR [r10+272]
+ mov r8, QWORD PTR [rcx+536]
+ mov QWORD PTR [rcx+528], rax
+ adc r8, QWORD PTR [r10+280]
+ mov rax, QWORD PTR [rcx+544]
+ mov QWORD PTR [rcx+536], r8
+ adc rax, QWORD PTR [r10+288]
+ mov r8, QWORD PTR [rcx+552]
+ mov QWORD PTR [rcx+544], rax
+ adc r8, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [rcx+560]
+ mov QWORD PTR [rcx+552], r8
+ adc rax, QWORD PTR [r10+304]
+ mov r8, QWORD PTR [rcx+568]
+ mov QWORD PTR [rcx+560], rax
+ adc r8, QWORD PTR [r10+312]
+ mov rax, QWORD PTR [rcx+576]
+ mov QWORD PTR [rcx+568], r8
+ adc rax, QWORD PTR [r10+320]
+ mov r8, QWORD PTR [rcx+584]
+ mov QWORD PTR [rcx+576], rax
+ adc r8, QWORD PTR [r10+328]
+ mov rax, QWORD PTR [rcx+592]
+ mov QWORD PTR [rcx+584], r8
+ adc rax, QWORD PTR [r10+336]
+ mov r8, QWORD PTR [rcx+600]
+ mov QWORD PTR [rcx+592], rax
+ adc r8, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [rcx+608]
+ mov QWORD PTR [rcx+600], r8
+ adc rax, QWORD PTR [r10+352]
+ mov r8, QWORD PTR [rcx+616]
+ mov QWORD PTR [rcx+608], rax
+ adc r8, QWORD PTR [r10+360]
+ mov rax, QWORD PTR [rcx+624]
+ mov QWORD PTR [rcx+616], r8
+ adc rax, QWORD PTR [r10+368]
+ mov r8, QWORD PTR [rcx+632]
+ mov QWORD PTR [rcx+624], rax
+ adc r8, QWORD PTR [r10+376]
+ mov rax, QWORD PTR [rcx+640]
+ mov QWORD PTR [rcx+632], r8
+ adc rax, QWORD PTR [r10+384]
+ mov r8, QWORD PTR [rcx+648]
+ mov QWORD PTR [rcx+640], rax
+ adc r8, QWORD PTR [r10+392]
+ mov rax, QWORD PTR [rcx+656]
+ mov QWORD PTR [rcx+648], r8
+ adc rax, QWORD PTR [r10+400]
+ mov r8, QWORD PTR [rcx+664]
+ mov QWORD PTR [rcx+656], rax
+ adc r8, QWORD PTR [r10+408]
+ mov rax, QWORD PTR [rcx+672]
+ mov QWORD PTR [rcx+664], r8
+ adc rax, QWORD PTR [r10+416]
+ mov r8, QWORD PTR [rcx+680]
+ mov QWORD PTR [rcx+672], rax
+ adc r8, QWORD PTR [r10+424]
+ mov rax, QWORD PTR [rcx+688]
+ mov QWORD PTR [rcx+680], r8
+ adc rax, QWORD PTR [r10+432]
+ mov r8, QWORD PTR [rcx+696]
+ mov QWORD PTR [rcx+688], rax
+ adc r8, QWORD PTR [r10+440]
+ mov rax, QWORD PTR [rcx+704]
+ mov QWORD PTR [rcx+696], r8
+ adc rax, QWORD PTR [r10+448]
+ mov r8, QWORD PTR [rcx+712]
+ mov QWORD PTR [rcx+704], rax
+ adc r8, QWORD PTR [r10+456]
+ mov rax, QWORD PTR [rcx+720]
+ mov QWORD PTR [rcx+712], r8
+ adc rax, QWORD PTR [r10+464]
+ mov r8, QWORD PTR [rcx+728]
+ mov QWORD PTR [rcx+720], rax
+ adc r8, QWORD PTR [r10+472]
+ mov rax, QWORD PTR [rcx+736]
+ mov QWORD PTR [rcx+728], r8
+ adc rax, QWORD PTR [r10+480]
+ mov r8, QWORD PTR [rcx+744]
+ mov QWORD PTR [rcx+736], rax
+ adc r8, QWORD PTR [r10+488]
+ mov rax, QWORD PTR [rcx+752]
+ mov QWORD PTR [rcx+744], r8
+ adc rax, QWORD PTR [r10+496]
+ mov r8, QWORD PTR [rcx+760]
+ mov QWORD PTR [rcx+752], rax
+ adc r8, QWORD PTR [r10+504]
+ mov QWORD PTR [rcx+760], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+768], r9
+ ; Add in place
+ mov rax, QWORD PTR [rcx+512]
+ xor r9, r9
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rcx+520]
+ mov QWORD PTR [rcx+512], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [rcx+528]
+ mov QWORD PTR [rcx+520], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rcx+536]
+ mov QWORD PTR [rcx+528], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rcx+544]
+ mov QWORD PTR [rcx+536], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rcx+552]
+ mov QWORD PTR [rcx+544], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [rcx+560]
+ mov QWORD PTR [rcx+552], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rcx+568]
+ mov QWORD PTR [rcx+560], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rcx+576]
+ mov QWORD PTR [rcx+568], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rcx+584]
+ mov QWORD PTR [rcx+576], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [rcx+592]
+ mov QWORD PTR [rcx+584], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rcx+600]
+ mov QWORD PTR [rcx+592], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rcx+608]
+ mov QWORD PTR [rcx+600], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rcx+616]
+ mov QWORD PTR [rcx+608], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [rcx+624]
+ mov QWORD PTR [rcx+616], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rcx+632]
+ mov QWORD PTR [rcx+624], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rcx+640]
+ mov QWORD PTR [rcx+632], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rcx+648]
+ mov QWORD PTR [rcx+640], rax
+ adc r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [rcx+656]
+ mov QWORD PTR [rcx+648], r8
+ adc rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rcx+664]
+ mov QWORD PTR [rcx+656], rax
+ adc r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [rcx+672]
+ mov QWORD PTR [rcx+664], r8
+ adc rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rcx+680]
+ mov QWORD PTR [rcx+672], rax
+ adc r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [rcx+688]
+ mov QWORD PTR [rcx+680], r8
+ adc rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rcx+696]
+ mov QWORD PTR [rcx+688], rax
+ adc r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [rcx+704]
+ mov QWORD PTR [rcx+696], r8
+ adc rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rcx+712]
+ mov QWORD PTR [rcx+704], rax
+ adc r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [rcx+720]
+ mov QWORD PTR [rcx+712], r8
+ adc rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rcx+728]
+ mov QWORD PTR [rcx+720], rax
+ adc r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [rcx+736]
+ mov QWORD PTR [rcx+728], r8
+ adc rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rcx+744]
+ mov QWORD PTR [rcx+736], rax
+ adc r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [rcx+752]
+ mov QWORD PTR [rcx+744], r8
+ adc rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rcx+760]
+ mov QWORD PTR [rcx+752], rax
+ adc r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [rcx+768]
+ mov QWORD PTR [rcx+760], r8
+ adc rax, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+768], rax
+ adc r9, 0
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+264]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+776], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+784], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+792], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+800], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+808], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+816], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+824], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+832], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+840], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+848], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+856], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+864], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+872], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+880], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+384]
+ mov QWORD PTR [rcx+888], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+392]
+ mov QWORD PTR [rcx+896], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+400]
+ mov QWORD PTR [rcx+904], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+408]
+ mov QWORD PTR [rcx+912], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+416]
+ mov QWORD PTR [rcx+920], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+424]
+ mov QWORD PTR [rcx+928], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+432]
+ mov QWORD PTR [rcx+936], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+440]
+ mov QWORD PTR [rcx+944], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+448]
+ mov QWORD PTR [rcx+952], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+456]
+ mov QWORD PTR [rcx+960], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+464]
+ mov QWORD PTR [rcx+968], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+472]
+ mov QWORD PTR [rcx+976], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+480]
+ mov QWORD PTR [rcx+984], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+488]
+ mov QWORD PTR [rcx+992], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+496]
+ mov QWORD PTR [rcx+1000], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+504]
+ mov QWORD PTR [rcx+1008], r8
+ adc rax, 0
+ mov QWORD PTR [rcx+1016], rax
+ add rsp, 1304
+ pop r12
+ ret
+sp_4096_sqr_64 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mul_avx2_64 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 1576
+ mov QWORD PTR [rsp+1536], rcx
+ mov QWORD PTR [rsp+1544], rdx
+ mov QWORD PTR [rsp+1552], r8
+ lea r12, QWORD PTR [rsp+1024]
+ lea r14, QWORD PTR [rdx+256]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r15, r15
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [r12], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov QWORD PTR [r12+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [rdx+24]
+ mov QWORD PTR [r12+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [r12+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [r12+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r12+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [rdx+56]
+ mov QWORD PTR [r12+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [rdx+64]
+ mov QWORD PTR [r12+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [rdx+72]
+ mov QWORD PTR [r12+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [r12+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [r12+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r12+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov QWORD PTR [r12+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov QWORD PTR [r12+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [rdx+120]
+ mov QWORD PTR [r12+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [r12+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [r12+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r12+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [rdx+152]
+ mov QWORD PTR [r12+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [rdx+160]
+ mov QWORD PTR [r12+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [rdx+168]
+ mov QWORD PTR [r12+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [r12+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [r12+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r12+184], r10
+ adc rax, QWORD PTR [r14+192]
+ mov r9, QWORD PTR [rdx+200]
+ mov QWORD PTR [r12+192], rax
+ adc r9, QWORD PTR [r14+200]
+ mov r10, QWORD PTR [rdx+208]
+ mov QWORD PTR [r12+200], r9
+ adc r10, QWORD PTR [r14+208]
+ mov rax, QWORD PTR [rdx+216]
+ mov QWORD PTR [r12+208], r10
+ adc rax, QWORD PTR [r14+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [r12+216], rax
+ adc r9, QWORD PTR [r14+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [r12+224], r9
+ adc r10, QWORD PTR [r14+232]
+ mov rax, QWORD PTR [rdx+240]
+ mov QWORD PTR [r12+232], r10
+ adc rax, QWORD PTR [r14+240]
+ mov r9, QWORD PTR [rdx+248]
+ mov QWORD PTR [r12+240], rax
+ adc r9, QWORD PTR [r14+248]
+ mov QWORD PTR [r12+248], r9
+ adc r15, 0
+ mov QWORD PTR [rsp+1560], r15
+ lea r13, QWORD PTR [rsp+1280]
+ lea r14, QWORD PTR [r8+256]
+ ; Add
+ mov rax, QWORD PTR [r8]
+ xor rdi, rdi
+ add rax, QWORD PTR [r14]
+ mov r9, QWORD PTR [r8+8]
+ mov QWORD PTR [r13], rax
+ adc r9, QWORD PTR [r14+8]
+ mov r10, QWORD PTR [r8+16]
+ mov QWORD PTR [r13+8], r9
+ adc r10, QWORD PTR [r14+16]
+ mov rax, QWORD PTR [r8+24]
+ mov QWORD PTR [r13+16], r10
+ adc rax, QWORD PTR [r14+24]
+ mov r9, QWORD PTR [r8+32]
+ mov QWORD PTR [r13+24], rax
+ adc r9, QWORD PTR [r14+32]
+ mov r10, QWORD PTR [r8+40]
+ mov QWORD PTR [r13+32], r9
+ adc r10, QWORD PTR [r14+40]
+ mov rax, QWORD PTR [r8+48]
+ mov QWORD PTR [r13+40], r10
+ adc rax, QWORD PTR [r14+48]
+ mov r9, QWORD PTR [r8+56]
+ mov QWORD PTR [r13+48], rax
+ adc r9, QWORD PTR [r14+56]
+ mov r10, QWORD PTR [r8+64]
+ mov QWORD PTR [r13+56], r9
+ adc r10, QWORD PTR [r14+64]
+ mov rax, QWORD PTR [r8+72]
+ mov QWORD PTR [r13+64], r10
+ adc rax, QWORD PTR [r14+72]
+ mov r9, QWORD PTR [r8+80]
+ mov QWORD PTR [r13+72], rax
+ adc r9, QWORD PTR [r14+80]
+ mov r10, QWORD PTR [r8+88]
+ mov QWORD PTR [r13+80], r9
+ adc r10, QWORD PTR [r14+88]
+ mov rax, QWORD PTR [r8+96]
+ mov QWORD PTR [r13+88], r10
+ adc rax, QWORD PTR [r14+96]
+ mov r9, QWORD PTR [r8+104]
+ mov QWORD PTR [r13+96], rax
+ adc r9, QWORD PTR [r14+104]
+ mov r10, QWORD PTR [r8+112]
+ mov QWORD PTR [r13+104], r9
+ adc r10, QWORD PTR [r14+112]
+ mov rax, QWORD PTR [r8+120]
+ mov QWORD PTR [r13+112], r10
+ adc rax, QWORD PTR [r14+120]
+ mov r9, QWORD PTR [r8+128]
+ mov QWORD PTR [r13+120], rax
+ adc r9, QWORD PTR [r14+128]
+ mov r10, QWORD PTR [r8+136]
+ mov QWORD PTR [r13+128], r9
+ adc r10, QWORD PTR [r14+136]
+ mov rax, QWORD PTR [r8+144]
+ mov QWORD PTR [r13+136], r10
+ adc rax, QWORD PTR [r14+144]
+ mov r9, QWORD PTR [r8+152]
+ mov QWORD PTR [r13+144], rax
+ adc r9, QWORD PTR [r14+152]
+ mov r10, QWORD PTR [r8+160]
+ mov QWORD PTR [r13+152], r9
+ adc r10, QWORD PTR [r14+160]
+ mov rax, QWORD PTR [r8+168]
+ mov QWORD PTR [r13+160], r10
+ adc rax, QWORD PTR [r14+168]
+ mov r9, QWORD PTR [r8+176]
+ mov QWORD PTR [r13+168], rax
+ adc r9, QWORD PTR [r14+176]
+ mov r10, QWORD PTR [r8+184]
+ mov QWORD PTR [r13+176], r9
+ adc r10, QWORD PTR [r14+184]
+ mov rax, QWORD PTR [r8+192]
+ mov QWORD PTR [r13+184], r10
+ adc rax, QWORD PTR [r14+192]
+ mov r9, QWORD PTR [r8+200]
+ mov QWORD PTR [r13+192], rax
+ adc r9, QWORD PTR [r14+200]
+ mov r10, QWORD PTR [r8+208]
+ mov QWORD PTR [r13+200], r9
+ adc r10, QWORD PTR [r14+208]
+ mov rax, QWORD PTR [r8+216]
+ mov QWORD PTR [r13+208], r10
+ adc rax, QWORD PTR [r14+216]
+ mov r9, QWORD PTR [r8+224]
+ mov QWORD PTR [r13+216], rax
+ adc r9, QWORD PTR [r14+224]
+ mov r10, QWORD PTR [r8+232]
+ mov QWORD PTR [r13+224], r9
+ adc r10, QWORD PTR [r14+232]
+ mov rax, QWORD PTR [r8+240]
+ mov QWORD PTR [r13+232], r10
+ adc rax, QWORD PTR [r14+240]
+ mov r9, QWORD PTR [r8+248]
+ mov QWORD PTR [r13+240], rax
+ adc r9, QWORD PTR [r14+248]
+ mov QWORD PTR [r13+248], r9
+ adc rdi, 0
+ mov QWORD PTR [rsp+1568], rdi
+ mov r8, r13
+ mov rdx, r12
+ mov rcx, rsp
+ call sp_2048_mul_avx2_32
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ lea rcx, QWORD PTR [rsp+512]
+ add r8, 256
+ add rdx, 256
+ call sp_2048_mul_avx2_32
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ mov rcx, QWORD PTR [rsp+1536]
+ call sp_2048_mul_avx2_32
+IFDEF _WIN64
+ mov r8, QWORD PTR [rsp+1552]
+ mov rdx, QWORD PTR [rsp+1544]
+ mov rcx, QWORD PTR [rsp+1536]
+ENDIF
+ mov r15, QWORD PTR [rsp+1560]
+ mov rdi, QWORD PTR [rsp+1568]
+ mov rsi, QWORD PTR [rsp+1536]
+ mov r11, r15
+ lea r12, QWORD PTR [rsp+1024]
+ lea r13, QWORD PTR [rsp+1280]
+ and r11, rdi
+ neg r15
+ neg rdi
+ add rsi, 512
+ mov rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [r13]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ add rax, r9
+ mov r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [r13+8]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [r13+16]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+8], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [r13+24]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+16], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [r13+32]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+24], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [r13+40]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+32], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [r13+48]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+40], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [r13+56]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+48], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [r13+64]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+56], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [r13+72]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+64], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [r13+80]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+72], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [r13+88]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+80], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [r13+96]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+88], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [r13+104]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+96], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [r13+112]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+104], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [r13+120]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+112], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [r13+128]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+120], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [r13+136]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+128], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [r13+144]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+136], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [r13+152]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+144], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [r13+160]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+152], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [r13+168]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+160], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [r13+176]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+168], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [r13+184]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+176], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [r13+192]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+184], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [r13+200]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+192], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [r13+208]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+200], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [r13+216]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+208], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [r13+224]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+216], rax
+ adc r9, r10
+ mov r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [r13+232]
+ pext r10, r10, rdi
+ pext rax, rax, r15
+ mov QWORD PTR [rsi+224], r9
+ adc r10, rax
+ mov rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [r13+240]
+ pext rax, rax, rdi
+ pext r9, r9, r15
+ mov QWORD PTR [rsi+232], r10
+ adc rax, r9
+ mov r9, QWORD PTR [r12+248]
+ mov r10, QWORD PTR [r13+248]
+ pext r9, r9, rdi
+ pext r10, r10, r15
+ mov QWORD PTR [rsi+240], rax
+ adc r9, r10
+ mov QWORD PTR [rsi+248], r9
+ adc r11, 0
+ lea r13, QWORD PTR [rsp+512]
+ mov r12, rsp
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [r13+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [r13+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [r13+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [r13+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [r13+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [r13+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [r13+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [r13+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [r13+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [r13+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [r13+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [r13+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [r13+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [r13+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [r13+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [r13+376]
+ mov rax, QWORD PTR [r12+384]
+ mov QWORD PTR [r12+376], r10
+ sbb rax, QWORD PTR [r13+384]
+ mov r9, QWORD PTR [r12+392]
+ mov QWORD PTR [r12+384], rax
+ sbb r9, QWORD PTR [r13+392]
+ mov r10, QWORD PTR [r12+400]
+ mov QWORD PTR [r12+392], r9
+ sbb r10, QWORD PTR [r13+400]
+ mov rax, QWORD PTR [r12+408]
+ mov QWORD PTR [r12+400], r10
+ sbb rax, QWORD PTR [r13+408]
+ mov r9, QWORD PTR [r12+416]
+ mov QWORD PTR [r12+408], rax
+ sbb r9, QWORD PTR [r13+416]
+ mov r10, QWORD PTR [r12+424]
+ mov QWORD PTR [r12+416], r9
+ sbb r10, QWORD PTR [r13+424]
+ mov rax, QWORD PTR [r12+432]
+ mov QWORD PTR [r12+424], r10
+ sbb rax, QWORD PTR [r13+432]
+ mov r9, QWORD PTR [r12+440]
+ mov QWORD PTR [r12+432], rax
+ sbb r9, QWORD PTR [r13+440]
+ mov r10, QWORD PTR [r12+448]
+ mov QWORD PTR [r12+440], r9
+ sbb r10, QWORD PTR [r13+448]
+ mov rax, QWORD PTR [r12+456]
+ mov QWORD PTR [r12+448], r10
+ sbb rax, QWORD PTR [r13+456]
+ mov r9, QWORD PTR [r12+464]
+ mov QWORD PTR [r12+456], rax
+ sbb r9, QWORD PTR [r13+464]
+ mov r10, QWORD PTR [r12+472]
+ mov QWORD PTR [r12+464], r9
+ sbb r10, QWORD PTR [r13+472]
+ mov rax, QWORD PTR [r12+480]
+ mov QWORD PTR [r12+472], r10
+ sbb rax, QWORD PTR [r13+480]
+ mov r9, QWORD PTR [r12+488]
+ mov QWORD PTR [r12+480], rax
+ sbb r9, QWORD PTR [r13+488]
+ mov r10, QWORD PTR [r12+496]
+ mov QWORD PTR [r12+488], r9
+ sbb r10, QWORD PTR [r13+496]
+ mov rax, QWORD PTR [r12+504]
+ mov QWORD PTR [r12+496], r10
+ sbb rax, QWORD PTR [r13+504]
+ mov QWORD PTR [r12+504], rax
+ sbb r11, 0
+ mov rax, QWORD PTR [r12]
+ sub rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [r12+8]
+ mov QWORD PTR [r12], rax
+ sbb r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [r12+16]
+ mov QWORD PTR [r12+8], r9
+ sbb r10, QWORD PTR [rcx+16]
+ mov rax, QWORD PTR [r12+24]
+ mov QWORD PTR [r12+16], r10
+ sbb rax, QWORD PTR [rcx+24]
+ mov r9, QWORD PTR [r12+32]
+ mov QWORD PTR [r12+24], rax
+ sbb r9, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [r12+40]
+ mov QWORD PTR [r12+32], r9
+ sbb r10, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r12+48]
+ mov QWORD PTR [r12+40], r10
+ sbb rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [r12+56]
+ mov QWORD PTR [r12+48], rax
+ sbb r9, QWORD PTR [rcx+56]
+ mov r10, QWORD PTR [r12+64]
+ mov QWORD PTR [r12+56], r9
+ sbb r10, QWORD PTR [rcx+64]
+ mov rax, QWORD PTR [r12+72]
+ mov QWORD PTR [r12+64], r10
+ sbb rax, QWORD PTR [rcx+72]
+ mov r9, QWORD PTR [r12+80]
+ mov QWORD PTR [r12+72], rax
+ sbb r9, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [r12+88]
+ mov QWORD PTR [r12+80], r9
+ sbb r10, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r12+96]
+ mov QWORD PTR [r12+88], r10
+ sbb rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [r12+104]
+ mov QWORD PTR [r12+96], rax
+ sbb r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [r12+112]
+ mov QWORD PTR [r12+104], r9
+ sbb r10, QWORD PTR [rcx+112]
+ mov rax, QWORD PTR [r12+120]
+ mov QWORD PTR [r12+112], r10
+ sbb rax, QWORD PTR [rcx+120]
+ mov r9, QWORD PTR [r12+128]
+ mov QWORD PTR [r12+120], rax
+ sbb r9, QWORD PTR [rcx+128]
+ mov r10, QWORD PTR [r12+136]
+ mov QWORD PTR [r12+128], r9
+ sbb r10, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r12+144]
+ mov QWORD PTR [r12+136], r10
+ sbb rax, QWORD PTR [rcx+144]
+ mov r9, QWORD PTR [r12+152]
+ mov QWORD PTR [r12+144], rax
+ sbb r9, QWORD PTR [rcx+152]
+ mov r10, QWORD PTR [r12+160]
+ mov QWORD PTR [r12+152], r9
+ sbb r10, QWORD PTR [rcx+160]
+ mov rax, QWORD PTR [r12+168]
+ mov QWORD PTR [r12+160], r10
+ sbb rax, QWORD PTR [rcx+168]
+ mov r9, QWORD PTR [r12+176]
+ mov QWORD PTR [r12+168], rax
+ sbb r9, QWORD PTR [rcx+176]
+ mov r10, QWORD PTR [r12+184]
+ mov QWORD PTR [r12+176], r9
+ sbb r10, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r12+192]
+ mov QWORD PTR [r12+184], r10
+ sbb rax, QWORD PTR [rcx+192]
+ mov r9, QWORD PTR [r12+200]
+ mov QWORD PTR [r12+192], rax
+ sbb r9, QWORD PTR [rcx+200]
+ mov r10, QWORD PTR [r12+208]
+ mov QWORD PTR [r12+200], r9
+ sbb r10, QWORD PTR [rcx+208]
+ mov rax, QWORD PTR [r12+216]
+ mov QWORD PTR [r12+208], r10
+ sbb rax, QWORD PTR [rcx+216]
+ mov r9, QWORD PTR [r12+224]
+ mov QWORD PTR [r12+216], rax
+ sbb r9, QWORD PTR [rcx+224]
+ mov r10, QWORD PTR [r12+232]
+ mov QWORD PTR [r12+224], r9
+ sbb r10, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r12+240]
+ mov QWORD PTR [r12+232], r10
+ sbb rax, QWORD PTR [rcx+240]
+ mov r9, QWORD PTR [r12+248]
+ mov QWORD PTR [r12+240], rax
+ sbb r9, QWORD PTR [rcx+248]
+ mov r10, QWORD PTR [r12+256]
+ mov QWORD PTR [r12+248], r9
+ sbb r10, QWORD PTR [rcx+256]
+ mov rax, QWORD PTR [r12+264]
+ mov QWORD PTR [r12+256], r10
+ sbb rax, QWORD PTR [rcx+264]
+ mov r9, QWORD PTR [r12+272]
+ mov QWORD PTR [r12+264], rax
+ sbb r9, QWORD PTR [rcx+272]
+ mov r10, QWORD PTR [r12+280]
+ mov QWORD PTR [r12+272], r9
+ sbb r10, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r12+288]
+ mov QWORD PTR [r12+280], r10
+ sbb rax, QWORD PTR [rcx+288]
+ mov r9, QWORD PTR [r12+296]
+ mov QWORD PTR [r12+288], rax
+ sbb r9, QWORD PTR [rcx+296]
+ mov r10, QWORD PTR [r12+304]
+ mov QWORD PTR [r12+296], r9
+ sbb r10, QWORD PTR [rcx+304]
+ mov rax, QWORD PTR [r12+312]
+ mov QWORD PTR [r12+304], r10
+ sbb rax, QWORD PTR [rcx+312]
+ mov r9, QWORD PTR [r12+320]
+ mov QWORD PTR [r12+312], rax
+ sbb r9, QWORD PTR [rcx+320]
+ mov r10, QWORD PTR [r12+328]
+ mov QWORD PTR [r12+320], r9
+ sbb r10, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r12+336]
+ mov QWORD PTR [r12+328], r10
+ sbb rax, QWORD PTR [rcx+336]
+ mov r9, QWORD PTR [r12+344]
+ mov QWORD PTR [r12+336], rax
+ sbb r9, QWORD PTR [rcx+344]
+ mov r10, QWORD PTR [r12+352]
+ mov QWORD PTR [r12+344], r9
+ sbb r10, QWORD PTR [rcx+352]
+ mov rax, QWORD PTR [r12+360]
+ mov QWORD PTR [r12+352], r10
+ sbb rax, QWORD PTR [rcx+360]
+ mov r9, QWORD PTR [r12+368]
+ mov QWORD PTR [r12+360], rax
+ sbb r9, QWORD PTR [rcx+368]
+ mov r10, QWORD PTR [r12+376]
+ mov QWORD PTR [r12+368], r9
+ sbb r10, QWORD PTR [rcx+376]
+ mov rax, QWORD PTR [r12+384]
+ mov QWORD PTR [r12+376], r10
+ sbb rax, QWORD PTR [rcx+384]
+ mov r9, QWORD PTR [r12+392]
+ mov QWORD PTR [r12+384], rax
+ sbb r9, QWORD PTR [rcx+392]
+ mov r10, QWORD PTR [r12+400]
+ mov QWORD PTR [r12+392], r9
+ sbb r10, QWORD PTR [rcx+400]
+ mov rax, QWORD PTR [r12+408]
+ mov QWORD PTR [r12+400], r10
+ sbb rax, QWORD PTR [rcx+408]
+ mov r9, QWORD PTR [r12+416]
+ mov QWORD PTR [r12+408], rax
+ sbb r9, QWORD PTR [rcx+416]
+ mov r10, QWORD PTR [r12+424]
+ mov QWORD PTR [r12+416], r9
+ sbb r10, QWORD PTR [rcx+424]
+ mov rax, QWORD PTR [r12+432]
+ mov QWORD PTR [r12+424], r10
+ sbb rax, QWORD PTR [rcx+432]
+ mov r9, QWORD PTR [r12+440]
+ mov QWORD PTR [r12+432], rax
+ sbb r9, QWORD PTR [rcx+440]
+ mov r10, QWORD PTR [r12+448]
+ mov QWORD PTR [r12+440], r9
+ sbb r10, QWORD PTR [rcx+448]
+ mov rax, QWORD PTR [r12+456]
+ mov QWORD PTR [r12+448], r10
+ sbb rax, QWORD PTR [rcx+456]
+ mov r9, QWORD PTR [r12+464]
+ mov QWORD PTR [r12+456], rax
+ sbb r9, QWORD PTR [rcx+464]
+ mov r10, QWORD PTR [r12+472]
+ mov QWORD PTR [r12+464], r9
+ sbb r10, QWORD PTR [rcx+472]
+ mov rax, QWORD PTR [r12+480]
+ mov QWORD PTR [r12+472], r10
+ sbb rax, QWORD PTR [rcx+480]
+ mov r9, QWORD PTR [r12+488]
+ mov QWORD PTR [r12+480], rax
+ sbb r9, QWORD PTR [rcx+488]
+ mov r10, QWORD PTR [r12+496]
+ mov QWORD PTR [r12+488], r9
+ sbb r10, QWORD PTR [rcx+496]
+ mov rax, QWORD PTR [r12+504]
+ mov QWORD PTR [r12+496], r10
+ sbb rax, QWORD PTR [rcx+504]
+ mov QWORD PTR [r12+504], rax
+ sbb r11, 0
+ sub rsi, 256
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ add rax, QWORD PTR [r12]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r12+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r12+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r12+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r12+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r12+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r12+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r12+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r12+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r12+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r12+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r12+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r12+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r12+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r12+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r12+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r12+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r12+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r12+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r12+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r12+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r12+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r12+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r12+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r12+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r12+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r12+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r12+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r12+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r12+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r12+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r12+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r12+256]
+ mov rax, QWORD PTR [rsi+264]
+ mov QWORD PTR [rsi+256], r10
+ adc rax, QWORD PTR [r12+264]
+ mov r9, QWORD PTR [rsi+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, QWORD PTR [r12+272]
+ mov r10, QWORD PTR [rsi+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, QWORD PTR [r12+280]
+ mov rax, QWORD PTR [rsi+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, QWORD PTR [r12+288]
+ mov r9, QWORD PTR [rsi+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, QWORD PTR [r12+296]
+ mov r10, QWORD PTR [rsi+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, QWORD PTR [r12+304]
+ mov rax, QWORD PTR [rsi+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, QWORD PTR [r12+312]
+ mov r9, QWORD PTR [rsi+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, QWORD PTR [r12+320]
+ mov r10, QWORD PTR [rsi+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, QWORD PTR [r12+328]
+ mov rax, QWORD PTR [rsi+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, QWORD PTR [r12+336]
+ mov r9, QWORD PTR [rsi+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, QWORD PTR [r12+344]
+ mov r10, QWORD PTR [rsi+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, QWORD PTR [r12+352]
+ mov rax, QWORD PTR [rsi+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, QWORD PTR [r12+360]
+ mov r9, QWORD PTR [rsi+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, QWORD PTR [r12+368]
+ mov r10, QWORD PTR [rsi+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, QWORD PTR [r12+376]
+ mov rax, QWORD PTR [rsi+384]
+ mov QWORD PTR [rsi+376], r10
+ adc rax, QWORD PTR [r12+384]
+ mov r9, QWORD PTR [rsi+392]
+ mov QWORD PTR [rsi+384], rax
+ adc r9, QWORD PTR [r12+392]
+ mov r10, QWORD PTR [rsi+400]
+ mov QWORD PTR [rsi+392], r9
+ adc r10, QWORD PTR [r12+400]
+ mov rax, QWORD PTR [rsi+408]
+ mov QWORD PTR [rsi+400], r10
+ adc rax, QWORD PTR [r12+408]
+ mov r9, QWORD PTR [rsi+416]
+ mov QWORD PTR [rsi+408], rax
+ adc r9, QWORD PTR [r12+416]
+ mov r10, QWORD PTR [rsi+424]
+ mov QWORD PTR [rsi+416], r9
+ adc r10, QWORD PTR [r12+424]
+ mov rax, QWORD PTR [rsi+432]
+ mov QWORD PTR [rsi+424], r10
+ adc rax, QWORD PTR [r12+432]
+ mov r9, QWORD PTR [rsi+440]
+ mov QWORD PTR [rsi+432], rax
+ adc r9, QWORD PTR [r12+440]
+ mov r10, QWORD PTR [rsi+448]
+ mov QWORD PTR [rsi+440], r9
+ adc r10, QWORD PTR [r12+448]
+ mov rax, QWORD PTR [rsi+456]
+ mov QWORD PTR [rsi+448], r10
+ adc rax, QWORD PTR [r12+456]
+ mov r9, QWORD PTR [rsi+464]
+ mov QWORD PTR [rsi+456], rax
+ adc r9, QWORD PTR [r12+464]
+ mov r10, QWORD PTR [rsi+472]
+ mov QWORD PTR [rsi+464], r9
+ adc r10, QWORD PTR [r12+472]
+ mov rax, QWORD PTR [rsi+480]
+ mov QWORD PTR [rsi+472], r10
+ adc rax, QWORD PTR [r12+480]
+ mov r9, QWORD PTR [rsi+488]
+ mov QWORD PTR [rsi+480], rax
+ adc r9, QWORD PTR [r12+488]
+ mov r10, QWORD PTR [rsi+496]
+ mov QWORD PTR [rsi+488], r9
+ adc r10, QWORD PTR [r12+496]
+ mov rax, QWORD PTR [rsi+504]
+ mov QWORD PTR [rsi+496], r10
+ adc rax, QWORD PTR [r12+504]
+ mov QWORD PTR [rsi+504], rax
+ adc r11, 0
+ mov QWORD PTR [rcx+768], r11
+ add rsi, 256
+ ; Add
+ mov rax, QWORD PTR [rsi]
+ xor r11, r11
+ add rax, QWORD PTR [r13]
+ mov r9, QWORD PTR [rsi+8]
+ mov QWORD PTR [rsi], rax
+ adc r9, QWORD PTR [r13+8]
+ mov r10, QWORD PTR [rsi+16]
+ mov QWORD PTR [rsi+8], r9
+ adc r10, QWORD PTR [r13+16]
+ mov rax, QWORD PTR [rsi+24]
+ mov QWORD PTR [rsi+16], r10
+ adc rax, QWORD PTR [r13+24]
+ mov r9, QWORD PTR [rsi+32]
+ mov QWORD PTR [rsi+24], rax
+ adc r9, QWORD PTR [r13+32]
+ mov r10, QWORD PTR [rsi+40]
+ mov QWORD PTR [rsi+32], r9
+ adc r10, QWORD PTR [r13+40]
+ mov rax, QWORD PTR [rsi+48]
+ mov QWORD PTR [rsi+40], r10
+ adc rax, QWORD PTR [r13+48]
+ mov r9, QWORD PTR [rsi+56]
+ mov QWORD PTR [rsi+48], rax
+ adc r9, QWORD PTR [r13+56]
+ mov r10, QWORD PTR [rsi+64]
+ mov QWORD PTR [rsi+56], r9
+ adc r10, QWORD PTR [r13+64]
+ mov rax, QWORD PTR [rsi+72]
+ mov QWORD PTR [rsi+64], r10
+ adc rax, QWORD PTR [r13+72]
+ mov r9, QWORD PTR [rsi+80]
+ mov QWORD PTR [rsi+72], rax
+ adc r9, QWORD PTR [r13+80]
+ mov r10, QWORD PTR [rsi+88]
+ mov QWORD PTR [rsi+80], r9
+ adc r10, QWORD PTR [r13+88]
+ mov rax, QWORD PTR [rsi+96]
+ mov QWORD PTR [rsi+88], r10
+ adc rax, QWORD PTR [r13+96]
+ mov r9, QWORD PTR [rsi+104]
+ mov QWORD PTR [rsi+96], rax
+ adc r9, QWORD PTR [r13+104]
+ mov r10, QWORD PTR [rsi+112]
+ mov QWORD PTR [rsi+104], r9
+ adc r10, QWORD PTR [r13+112]
+ mov rax, QWORD PTR [rsi+120]
+ mov QWORD PTR [rsi+112], r10
+ adc rax, QWORD PTR [r13+120]
+ mov r9, QWORD PTR [rsi+128]
+ mov QWORD PTR [rsi+120], rax
+ adc r9, QWORD PTR [r13+128]
+ mov r10, QWORD PTR [rsi+136]
+ mov QWORD PTR [rsi+128], r9
+ adc r10, QWORD PTR [r13+136]
+ mov rax, QWORD PTR [rsi+144]
+ mov QWORD PTR [rsi+136], r10
+ adc rax, QWORD PTR [r13+144]
+ mov r9, QWORD PTR [rsi+152]
+ mov QWORD PTR [rsi+144], rax
+ adc r9, QWORD PTR [r13+152]
+ mov r10, QWORD PTR [rsi+160]
+ mov QWORD PTR [rsi+152], r9
+ adc r10, QWORD PTR [r13+160]
+ mov rax, QWORD PTR [rsi+168]
+ mov QWORD PTR [rsi+160], r10
+ adc rax, QWORD PTR [r13+168]
+ mov r9, QWORD PTR [rsi+176]
+ mov QWORD PTR [rsi+168], rax
+ adc r9, QWORD PTR [r13+176]
+ mov r10, QWORD PTR [rsi+184]
+ mov QWORD PTR [rsi+176], r9
+ adc r10, QWORD PTR [r13+184]
+ mov rax, QWORD PTR [rsi+192]
+ mov QWORD PTR [rsi+184], r10
+ adc rax, QWORD PTR [r13+192]
+ mov r9, QWORD PTR [rsi+200]
+ mov QWORD PTR [rsi+192], rax
+ adc r9, QWORD PTR [r13+200]
+ mov r10, QWORD PTR [rsi+208]
+ mov QWORD PTR [rsi+200], r9
+ adc r10, QWORD PTR [r13+208]
+ mov rax, QWORD PTR [rsi+216]
+ mov QWORD PTR [rsi+208], r10
+ adc rax, QWORD PTR [r13+216]
+ mov r9, QWORD PTR [rsi+224]
+ mov QWORD PTR [rsi+216], rax
+ adc r9, QWORD PTR [r13+224]
+ mov r10, QWORD PTR [rsi+232]
+ mov QWORD PTR [rsi+224], r9
+ adc r10, QWORD PTR [r13+232]
+ mov rax, QWORD PTR [rsi+240]
+ mov QWORD PTR [rsi+232], r10
+ adc rax, QWORD PTR [r13+240]
+ mov r9, QWORD PTR [rsi+248]
+ mov QWORD PTR [rsi+240], rax
+ adc r9, QWORD PTR [r13+248]
+ mov r10, QWORD PTR [rsi+256]
+ mov QWORD PTR [rsi+248], r9
+ adc r10, QWORD PTR [r13+256]
+ mov QWORD PTR [rsi+256], r10
+ adc r11, 0
+ ; Add to zero
+ mov rax, QWORD PTR [r13+264]
+ adc rax, 0
+ mov r9, QWORD PTR [r13+272]
+ mov QWORD PTR [rsi+264], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+280]
+ mov QWORD PTR [rsi+272], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+288]
+ mov QWORD PTR [rsi+280], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+296]
+ mov QWORD PTR [rsi+288], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+304]
+ mov QWORD PTR [rsi+296], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+312]
+ mov QWORD PTR [rsi+304], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+320]
+ mov QWORD PTR [rsi+312], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+328]
+ mov QWORD PTR [rsi+320], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+336]
+ mov QWORD PTR [rsi+328], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+344]
+ mov QWORD PTR [rsi+336], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+352]
+ mov QWORD PTR [rsi+344], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+360]
+ mov QWORD PTR [rsi+352], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+368]
+ mov QWORD PTR [rsi+360], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+376]
+ mov QWORD PTR [rsi+368], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+384]
+ mov QWORD PTR [rsi+376], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+392]
+ mov QWORD PTR [rsi+384], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+400]
+ mov QWORD PTR [rsi+392], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+408]
+ mov QWORD PTR [rsi+400], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+416]
+ mov QWORD PTR [rsi+408], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+424]
+ mov QWORD PTR [rsi+416], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+432]
+ mov QWORD PTR [rsi+424], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+440]
+ mov QWORD PTR [rsi+432], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+448]
+ mov QWORD PTR [rsi+440], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+456]
+ mov QWORD PTR [rsi+448], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+464]
+ mov QWORD PTR [rsi+456], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+472]
+ mov QWORD PTR [rsi+464], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+480]
+ mov QWORD PTR [rsi+472], r10
+ adc rax, 0
+ mov r9, QWORD PTR [r13+488]
+ mov QWORD PTR [rsi+480], rax
+ adc r9, 0
+ mov r10, QWORD PTR [r13+496]
+ mov QWORD PTR [rsi+488], r9
+ adc r10, 0
+ mov rax, QWORD PTR [r13+504]
+ mov QWORD PTR [rsi+496], r10
+ adc rax, 0
+ mov QWORD PTR [rsi+504], rax
+ add rsp, 1576
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_4096_mul_avx2_64 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_sqr_avx2_64 PROC
+ push r12
+ sub rsp, 1304
+ mov QWORD PTR [rsp+1280], rcx
+ mov QWORD PTR [rsp+1288], rdx
+ lea r10, QWORD PTR [rsp+1024]
+ lea r11, QWORD PTR [rdx+256]
+ ; Add
+ mov rax, QWORD PTR [rdx]
+ xor r9, r9
+ add rax, QWORD PTR [r11]
+ mov r8, QWORD PTR [rdx+8]
+ mov QWORD PTR [r10], rax
+ adc r8, QWORD PTR [r11+8]
+ mov rax, QWORD PTR [rdx+16]
+ mov QWORD PTR [r10+8], r8
+ adc rax, QWORD PTR [r11+16]
+ mov r8, QWORD PTR [rdx+24]
+ mov QWORD PTR [r10+16], rax
+ adc r8, QWORD PTR [r11+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov QWORD PTR [r10+24], r8
+ adc rax, QWORD PTR [r11+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov QWORD PTR [r10+32], rax
+ adc r8, QWORD PTR [r11+40]
+ mov rax, QWORD PTR [rdx+48]
+ mov QWORD PTR [r10+40], r8
+ adc rax, QWORD PTR [r11+48]
+ mov r8, QWORD PTR [rdx+56]
+ mov QWORD PTR [r10+48], rax
+ adc r8, QWORD PTR [r11+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov QWORD PTR [r10+56], r8
+ adc rax, QWORD PTR [r11+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov QWORD PTR [r10+64], rax
+ adc r8, QWORD PTR [r11+72]
+ mov rax, QWORD PTR [rdx+80]
+ mov QWORD PTR [r10+72], r8
+ adc rax, QWORD PTR [r11+80]
+ mov r8, QWORD PTR [rdx+88]
+ mov QWORD PTR [r10+80], rax
+ adc r8, QWORD PTR [r11+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov QWORD PTR [r10+88], r8
+ adc rax, QWORD PTR [r11+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov QWORD PTR [r10+96], rax
+ adc r8, QWORD PTR [r11+104]
+ mov rax, QWORD PTR [rdx+112]
+ mov QWORD PTR [r10+104], r8
+ adc rax, QWORD PTR [r11+112]
+ mov r8, QWORD PTR [rdx+120]
+ mov QWORD PTR [r10+112], rax
+ adc r8, QWORD PTR [r11+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov QWORD PTR [r10+120], r8
+ adc rax, QWORD PTR [r11+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov QWORD PTR [r10+128], rax
+ adc r8, QWORD PTR [r11+136]
+ mov rax, QWORD PTR [rdx+144]
+ mov QWORD PTR [r10+136], r8
+ adc rax, QWORD PTR [r11+144]
+ mov r8, QWORD PTR [rdx+152]
+ mov QWORD PTR [r10+144], rax
+ adc r8, QWORD PTR [r11+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov QWORD PTR [r10+152], r8
+ adc rax, QWORD PTR [r11+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov QWORD PTR [r10+160], rax
+ adc r8, QWORD PTR [r11+168]
+ mov rax, QWORD PTR [rdx+176]
+ mov QWORD PTR [r10+168], r8
+ adc rax, QWORD PTR [r11+176]
+ mov r8, QWORD PTR [rdx+184]
+ mov QWORD PTR [r10+176], rax
+ adc r8, QWORD PTR [r11+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov QWORD PTR [r10+184], r8
+ adc rax, QWORD PTR [r11+192]
+ mov r8, QWORD PTR [rdx+200]
+ mov QWORD PTR [r10+192], rax
+ adc r8, QWORD PTR [r11+200]
+ mov rax, QWORD PTR [rdx+208]
+ mov QWORD PTR [r10+200], r8
+ adc rax, QWORD PTR [r11+208]
+ mov r8, QWORD PTR [rdx+216]
+ mov QWORD PTR [r10+208], rax
+ adc r8, QWORD PTR [r11+216]
+ mov rax, QWORD PTR [rdx+224]
+ mov QWORD PTR [r10+216], r8
+ adc rax, QWORD PTR [r11+224]
+ mov r8, QWORD PTR [rdx+232]
+ mov QWORD PTR [r10+224], rax
+ adc r8, QWORD PTR [r11+232]
+ mov rax, QWORD PTR [rdx+240]
+ mov QWORD PTR [r10+232], r8
+ adc rax, QWORD PTR [r11+240]
+ mov r8, QWORD PTR [rdx+248]
+ mov QWORD PTR [r10+240], rax
+ adc r8, QWORD PTR [r11+248]
+ mov QWORD PTR [r10+248], r8
+ adc r9, 0
+ mov QWORD PTR [rsp+1296], r9
+ mov rdx, r10
+ mov rcx, rsp
+ call sp_2048_sqr_avx2_32
+ mov rdx, QWORD PTR [rsp+1288]
+ lea rcx, QWORD PTR [rsp+512]
+ add rdx, 256
+ call sp_2048_sqr_avx2_32
+ mov rdx, QWORD PTR [rsp+1288]
+ mov rcx, QWORD PTR [rsp+1280]
+ call sp_2048_sqr_avx2_32
+IFDEF _WIN64
+ mov rdx, QWORD PTR [rsp+1288]
+ mov rcx, QWORD PTR [rsp+1280]
+ENDIF
+ mov r12, QWORD PTR [rsp+1296]
+ lea r10, QWORD PTR [rsp+1024]
+ mov r9, r12
+ neg r12
+ mov rax, QWORD PTR [r10]
+ pext rax, rax, r12
+ add rax, rax
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [rcx+512], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [rcx+520], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [rcx+528], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [rcx+536], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [rcx+544], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [rcx+552], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [rcx+560], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [rcx+568], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [rcx+576], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [rcx+584], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [rcx+592], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [rcx+600], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [rcx+608], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [rcx+616], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [rcx+624], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [rcx+632], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [rcx+640], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [rcx+648], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [rcx+656], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [rcx+664], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [rcx+672], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [rcx+680], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [rcx+688], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [rcx+696], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [rcx+704], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [rcx+712], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [rcx+720], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [rcx+728], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [rcx+736], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [rcx+744], r8
+ pext rax, rax, r12
+ adc rax, rax
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [rcx+752], rax
+ pext r8, r8, r12
+ adc r8, r8
+ mov QWORD PTR [rcx+760], r8
+ adc r9, 0
+ lea rdx, QWORD PTR [rsp+512]
+ mov r10, rsp
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rdx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rdx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rdx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rdx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rdx+376]
+ mov rax, QWORD PTR [r10+384]
+ mov QWORD PTR [r10+376], r8
+ sbb rax, QWORD PTR [rdx+384]
+ mov r8, QWORD PTR [r10+392]
+ mov QWORD PTR [r10+384], rax
+ sbb r8, QWORD PTR [rdx+392]
+ mov rax, QWORD PTR [r10+400]
+ mov QWORD PTR [r10+392], r8
+ sbb rax, QWORD PTR [rdx+400]
+ mov r8, QWORD PTR [r10+408]
+ mov QWORD PTR [r10+400], rax
+ sbb r8, QWORD PTR [rdx+408]
+ mov rax, QWORD PTR [r10+416]
+ mov QWORD PTR [r10+408], r8
+ sbb rax, QWORD PTR [rdx+416]
+ mov r8, QWORD PTR [r10+424]
+ mov QWORD PTR [r10+416], rax
+ sbb r8, QWORD PTR [rdx+424]
+ mov rax, QWORD PTR [r10+432]
+ mov QWORD PTR [r10+424], r8
+ sbb rax, QWORD PTR [rdx+432]
+ mov r8, QWORD PTR [r10+440]
+ mov QWORD PTR [r10+432], rax
+ sbb r8, QWORD PTR [rdx+440]
+ mov rax, QWORD PTR [r10+448]
+ mov QWORD PTR [r10+440], r8
+ sbb rax, QWORD PTR [rdx+448]
+ mov r8, QWORD PTR [r10+456]
+ mov QWORD PTR [r10+448], rax
+ sbb r8, QWORD PTR [rdx+456]
+ mov rax, QWORD PTR [r10+464]
+ mov QWORD PTR [r10+456], r8
+ sbb rax, QWORD PTR [rdx+464]
+ mov r8, QWORD PTR [r10+472]
+ mov QWORD PTR [r10+464], rax
+ sbb r8, QWORD PTR [rdx+472]
+ mov rax, QWORD PTR [r10+480]
+ mov QWORD PTR [r10+472], r8
+ sbb rax, QWORD PTR [rdx+480]
+ mov r8, QWORD PTR [r10+488]
+ mov QWORD PTR [r10+480], rax
+ sbb r8, QWORD PTR [rdx+488]
+ mov rax, QWORD PTR [r10+496]
+ mov QWORD PTR [r10+488], r8
+ sbb rax, QWORD PTR [rdx+496]
+ mov r8, QWORD PTR [r10+504]
+ mov QWORD PTR [r10+496], rax
+ sbb r8, QWORD PTR [rdx+504]
+ mov QWORD PTR [r10+504], r8
+ sbb r9, 0
+ mov rax, QWORD PTR [r10]
+ sub rax, QWORD PTR [rcx]
+ mov r8, QWORD PTR [r10+8]
+ mov QWORD PTR [r10], rax
+ sbb r8, QWORD PTR [rcx+8]
+ mov rax, QWORD PTR [r10+16]
+ mov QWORD PTR [r10+8], r8
+ sbb rax, QWORD PTR [rcx+16]
+ mov r8, QWORD PTR [r10+24]
+ mov QWORD PTR [r10+16], rax
+ sbb r8, QWORD PTR [rcx+24]
+ mov rax, QWORD PTR [r10+32]
+ mov QWORD PTR [r10+24], r8
+ sbb rax, QWORD PTR [rcx+32]
+ mov r8, QWORD PTR [r10+40]
+ mov QWORD PTR [r10+32], rax
+ sbb r8, QWORD PTR [rcx+40]
+ mov rax, QWORD PTR [r10+48]
+ mov QWORD PTR [r10+40], r8
+ sbb rax, QWORD PTR [rcx+48]
+ mov r8, QWORD PTR [r10+56]
+ mov QWORD PTR [r10+48], rax
+ sbb r8, QWORD PTR [rcx+56]
+ mov rax, QWORD PTR [r10+64]
+ mov QWORD PTR [r10+56], r8
+ sbb rax, QWORD PTR [rcx+64]
+ mov r8, QWORD PTR [r10+72]
+ mov QWORD PTR [r10+64], rax
+ sbb r8, QWORD PTR [rcx+72]
+ mov rax, QWORD PTR [r10+80]
+ mov QWORD PTR [r10+72], r8
+ sbb rax, QWORD PTR [rcx+80]
+ mov r8, QWORD PTR [r10+88]
+ mov QWORD PTR [r10+80], rax
+ sbb r8, QWORD PTR [rcx+88]
+ mov rax, QWORD PTR [r10+96]
+ mov QWORD PTR [r10+88], r8
+ sbb rax, QWORD PTR [rcx+96]
+ mov r8, QWORD PTR [r10+104]
+ mov QWORD PTR [r10+96], rax
+ sbb r8, QWORD PTR [rcx+104]
+ mov rax, QWORD PTR [r10+112]
+ mov QWORD PTR [r10+104], r8
+ sbb rax, QWORD PTR [rcx+112]
+ mov r8, QWORD PTR [r10+120]
+ mov QWORD PTR [r10+112], rax
+ sbb r8, QWORD PTR [rcx+120]
+ mov rax, QWORD PTR [r10+128]
+ mov QWORD PTR [r10+120], r8
+ sbb rax, QWORD PTR [rcx+128]
+ mov r8, QWORD PTR [r10+136]
+ mov QWORD PTR [r10+128], rax
+ sbb r8, QWORD PTR [rcx+136]
+ mov rax, QWORD PTR [r10+144]
+ mov QWORD PTR [r10+136], r8
+ sbb rax, QWORD PTR [rcx+144]
+ mov r8, QWORD PTR [r10+152]
+ mov QWORD PTR [r10+144], rax
+ sbb r8, QWORD PTR [rcx+152]
+ mov rax, QWORD PTR [r10+160]
+ mov QWORD PTR [r10+152], r8
+ sbb rax, QWORD PTR [rcx+160]
+ mov r8, QWORD PTR [r10+168]
+ mov QWORD PTR [r10+160], rax
+ sbb r8, QWORD PTR [rcx+168]
+ mov rax, QWORD PTR [r10+176]
+ mov QWORD PTR [r10+168], r8
+ sbb rax, QWORD PTR [rcx+176]
+ mov r8, QWORD PTR [r10+184]
+ mov QWORD PTR [r10+176], rax
+ sbb r8, QWORD PTR [rcx+184]
+ mov rax, QWORD PTR [r10+192]
+ mov QWORD PTR [r10+184], r8
+ sbb rax, QWORD PTR [rcx+192]
+ mov r8, QWORD PTR [r10+200]
+ mov QWORD PTR [r10+192], rax
+ sbb r8, QWORD PTR [rcx+200]
+ mov rax, QWORD PTR [r10+208]
+ mov QWORD PTR [r10+200], r8
+ sbb rax, QWORD PTR [rcx+208]
+ mov r8, QWORD PTR [r10+216]
+ mov QWORD PTR [r10+208], rax
+ sbb r8, QWORD PTR [rcx+216]
+ mov rax, QWORD PTR [r10+224]
+ mov QWORD PTR [r10+216], r8
+ sbb rax, QWORD PTR [rcx+224]
+ mov r8, QWORD PTR [r10+232]
+ mov QWORD PTR [r10+224], rax
+ sbb r8, QWORD PTR [rcx+232]
+ mov rax, QWORD PTR [r10+240]
+ mov QWORD PTR [r10+232], r8
+ sbb rax, QWORD PTR [rcx+240]
+ mov r8, QWORD PTR [r10+248]
+ mov QWORD PTR [r10+240], rax
+ sbb r8, QWORD PTR [rcx+248]
+ mov rax, QWORD PTR [r10+256]
+ mov QWORD PTR [r10+248], r8
+ sbb rax, QWORD PTR [rcx+256]
+ mov r8, QWORD PTR [r10+264]
+ mov QWORD PTR [r10+256], rax
+ sbb r8, QWORD PTR [rcx+264]
+ mov rax, QWORD PTR [r10+272]
+ mov QWORD PTR [r10+264], r8
+ sbb rax, QWORD PTR [rcx+272]
+ mov r8, QWORD PTR [r10+280]
+ mov QWORD PTR [r10+272], rax
+ sbb r8, QWORD PTR [rcx+280]
+ mov rax, QWORD PTR [r10+288]
+ mov QWORD PTR [r10+280], r8
+ sbb rax, QWORD PTR [rcx+288]
+ mov r8, QWORD PTR [r10+296]
+ mov QWORD PTR [r10+288], rax
+ sbb r8, QWORD PTR [rcx+296]
+ mov rax, QWORD PTR [r10+304]
+ mov QWORD PTR [r10+296], r8
+ sbb rax, QWORD PTR [rcx+304]
+ mov r8, QWORD PTR [r10+312]
+ mov QWORD PTR [r10+304], rax
+ sbb r8, QWORD PTR [rcx+312]
+ mov rax, QWORD PTR [r10+320]
+ mov QWORD PTR [r10+312], r8
+ sbb rax, QWORD PTR [rcx+320]
+ mov r8, QWORD PTR [r10+328]
+ mov QWORD PTR [r10+320], rax
+ sbb r8, QWORD PTR [rcx+328]
+ mov rax, QWORD PTR [r10+336]
+ mov QWORD PTR [r10+328], r8
+ sbb rax, QWORD PTR [rcx+336]
+ mov r8, QWORD PTR [r10+344]
+ mov QWORD PTR [r10+336], rax
+ sbb r8, QWORD PTR [rcx+344]
+ mov rax, QWORD PTR [r10+352]
+ mov QWORD PTR [r10+344], r8
+ sbb rax, QWORD PTR [rcx+352]
+ mov r8, QWORD PTR [r10+360]
+ mov QWORD PTR [r10+352], rax
+ sbb r8, QWORD PTR [rcx+360]
+ mov rax, QWORD PTR [r10+368]
+ mov QWORD PTR [r10+360], r8
+ sbb rax, QWORD PTR [rcx+368]
+ mov r8, QWORD PTR [r10+376]
+ mov QWORD PTR [r10+368], rax
+ sbb r8, QWORD PTR [rcx+376]
+ mov rax, QWORD PTR [r10+384]
+ mov QWORD PTR [r10+376], r8
+ sbb rax, QWORD PTR [rcx+384]
+ mov r8, QWORD PTR [r10+392]
+ mov QWORD PTR [r10+384], rax
+ sbb r8, QWORD PTR [rcx+392]
+ mov rax, QWORD PTR [r10+400]
+ mov QWORD PTR [r10+392], r8
+ sbb rax, QWORD PTR [rcx+400]
+ mov r8, QWORD PTR [r10+408]
+ mov QWORD PTR [r10+400], rax
+ sbb r8, QWORD PTR [rcx+408]
+ mov rax, QWORD PTR [r10+416]
+ mov QWORD PTR [r10+408], r8
+ sbb rax, QWORD PTR [rcx+416]
+ mov r8, QWORD PTR [r10+424]
+ mov QWORD PTR [r10+416], rax
+ sbb r8, QWORD PTR [rcx+424]
+ mov rax, QWORD PTR [r10+432]
+ mov QWORD PTR [r10+424], r8
+ sbb rax, QWORD PTR [rcx+432]
+ mov r8, QWORD PTR [r10+440]
+ mov QWORD PTR [r10+432], rax
+ sbb r8, QWORD PTR [rcx+440]
+ mov rax, QWORD PTR [r10+448]
+ mov QWORD PTR [r10+440], r8
+ sbb rax, QWORD PTR [rcx+448]
+ mov r8, QWORD PTR [r10+456]
+ mov QWORD PTR [r10+448], rax
+ sbb r8, QWORD PTR [rcx+456]
+ mov rax, QWORD PTR [r10+464]
+ mov QWORD PTR [r10+456], r8
+ sbb rax, QWORD PTR [rcx+464]
+ mov r8, QWORD PTR [r10+472]
+ mov QWORD PTR [r10+464], rax
+ sbb r8, QWORD PTR [rcx+472]
+ mov rax, QWORD PTR [r10+480]
+ mov QWORD PTR [r10+472], r8
+ sbb rax, QWORD PTR [rcx+480]
+ mov r8, QWORD PTR [r10+488]
+ mov QWORD PTR [r10+480], rax
+ sbb r8, QWORD PTR [rcx+488]
+ mov rax, QWORD PTR [r10+496]
+ mov QWORD PTR [r10+488], r8
+ sbb rax, QWORD PTR [rcx+496]
+ mov r8, QWORD PTR [r10+504]
+ mov QWORD PTR [r10+496], rax
+ sbb r8, QWORD PTR [rcx+504]
+ mov QWORD PTR [r10+504], r8
+ sbb r9, 0
+ ; Add in place
+ mov rax, QWORD PTR [rcx+256]
+ add rax, QWORD PTR [r10]
+ mov r8, QWORD PTR [rcx+264]
+ mov QWORD PTR [rcx+256], rax
+ adc r8, QWORD PTR [r10+8]
+ mov rax, QWORD PTR [rcx+272]
+ mov QWORD PTR [rcx+264], r8
+ adc rax, QWORD PTR [r10+16]
+ mov r8, QWORD PTR [rcx+280]
+ mov QWORD PTR [rcx+272], rax
+ adc r8, QWORD PTR [r10+24]
+ mov rax, QWORD PTR [rcx+288]
+ mov QWORD PTR [rcx+280], r8
+ adc rax, QWORD PTR [r10+32]
+ mov r8, QWORD PTR [rcx+296]
+ mov QWORD PTR [rcx+288], rax
+ adc r8, QWORD PTR [r10+40]
+ mov rax, QWORD PTR [rcx+304]
+ mov QWORD PTR [rcx+296], r8
+ adc rax, QWORD PTR [r10+48]
+ mov r8, QWORD PTR [rcx+312]
+ mov QWORD PTR [rcx+304], rax
+ adc r8, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [rcx+320]
+ mov QWORD PTR [rcx+312], r8
+ adc rax, QWORD PTR [r10+64]
+ mov r8, QWORD PTR [rcx+328]
+ mov QWORD PTR [rcx+320], rax
+ adc r8, QWORD PTR [r10+72]
+ mov rax, QWORD PTR [rcx+336]
+ mov QWORD PTR [rcx+328], r8
+ adc rax, QWORD PTR [r10+80]
+ mov r8, QWORD PTR [rcx+344]
+ mov QWORD PTR [rcx+336], rax
+ adc r8, QWORD PTR [r10+88]
+ mov rax, QWORD PTR [rcx+352]
+ mov QWORD PTR [rcx+344], r8
+ adc rax, QWORD PTR [r10+96]
+ mov r8, QWORD PTR [rcx+360]
+ mov QWORD PTR [rcx+352], rax
+ adc r8, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [rcx+368]
+ mov QWORD PTR [rcx+360], r8
+ adc rax, QWORD PTR [r10+112]
+ mov r8, QWORD PTR [rcx+376]
+ mov QWORD PTR [rcx+368], rax
+ adc r8, QWORD PTR [r10+120]
+ mov rax, QWORD PTR [rcx+384]
+ mov QWORD PTR [rcx+376], r8
+ adc rax, QWORD PTR [r10+128]
+ mov r8, QWORD PTR [rcx+392]
+ mov QWORD PTR [rcx+384], rax
+ adc r8, QWORD PTR [r10+136]
+ mov rax, QWORD PTR [rcx+400]
+ mov QWORD PTR [rcx+392], r8
+ adc rax, QWORD PTR [r10+144]
+ mov r8, QWORD PTR [rcx+408]
+ mov QWORD PTR [rcx+400], rax
+ adc r8, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [rcx+416]
+ mov QWORD PTR [rcx+408], r8
+ adc rax, QWORD PTR [r10+160]
+ mov r8, QWORD PTR [rcx+424]
+ mov QWORD PTR [rcx+416], rax
+ adc r8, QWORD PTR [r10+168]
+ mov rax, QWORD PTR [rcx+432]
+ mov QWORD PTR [rcx+424], r8
+ adc rax, QWORD PTR [r10+176]
+ mov r8, QWORD PTR [rcx+440]
+ mov QWORD PTR [rcx+432], rax
+ adc r8, QWORD PTR [r10+184]
+ mov rax, QWORD PTR [rcx+448]
+ mov QWORD PTR [rcx+440], r8
+ adc rax, QWORD PTR [r10+192]
+ mov r8, QWORD PTR [rcx+456]
+ mov QWORD PTR [rcx+448], rax
+ adc r8, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [rcx+464]
+ mov QWORD PTR [rcx+456], r8
+ adc rax, QWORD PTR [r10+208]
+ mov r8, QWORD PTR [rcx+472]
+ mov QWORD PTR [rcx+464], rax
+ adc r8, QWORD PTR [r10+216]
+ mov rax, QWORD PTR [rcx+480]
+ mov QWORD PTR [rcx+472], r8
+ adc rax, QWORD PTR [r10+224]
+ mov r8, QWORD PTR [rcx+488]
+ mov QWORD PTR [rcx+480], rax
+ adc r8, QWORD PTR [r10+232]
+ mov rax, QWORD PTR [rcx+496]
+ mov QWORD PTR [rcx+488], r8
+ adc rax, QWORD PTR [r10+240]
+ mov r8, QWORD PTR [rcx+504]
+ mov QWORD PTR [rcx+496], rax
+ adc r8, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [rcx+512]
+ mov QWORD PTR [rcx+504], r8
+ adc rax, QWORD PTR [r10+256]
+ mov r8, QWORD PTR [rcx+520]
+ mov QWORD PTR [rcx+512], rax
+ adc r8, QWORD PTR [r10+264]
+ mov rax, QWORD PTR [rcx+528]
+ mov QWORD PTR [rcx+520], r8
+ adc rax, QWORD PTR [r10+272]
+ mov r8, QWORD PTR [rcx+536]
+ mov QWORD PTR [rcx+528], rax
+ adc r8, QWORD PTR [r10+280]
+ mov rax, QWORD PTR [rcx+544]
+ mov QWORD PTR [rcx+536], r8
+ adc rax, QWORD PTR [r10+288]
+ mov r8, QWORD PTR [rcx+552]
+ mov QWORD PTR [rcx+544], rax
+ adc r8, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [rcx+560]
+ mov QWORD PTR [rcx+552], r8
+ adc rax, QWORD PTR [r10+304]
+ mov r8, QWORD PTR [rcx+568]
+ mov QWORD PTR [rcx+560], rax
+ adc r8, QWORD PTR [r10+312]
+ mov rax, QWORD PTR [rcx+576]
+ mov QWORD PTR [rcx+568], r8
+ adc rax, QWORD PTR [r10+320]
+ mov r8, QWORD PTR [rcx+584]
+ mov QWORD PTR [rcx+576], rax
+ adc r8, QWORD PTR [r10+328]
+ mov rax, QWORD PTR [rcx+592]
+ mov QWORD PTR [rcx+584], r8
+ adc rax, QWORD PTR [r10+336]
+ mov r8, QWORD PTR [rcx+600]
+ mov QWORD PTR [rcx+592], rax
+ adc r8, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [rcx+608]
+ mov QWORD PTR [rcx+600], r8
+ adc rax, QWORD PTR [r10+352]
+ mov r8, QWORD PTR [rcx+616]
+ mov QWORD PTR [rcx+608], rax
+ adc r8, QWORD PTR [r10+360]
+ mov rax, QWORD PTR [rcx+624]
+ mov QWORD PTR [rcx+616], r8
+ adc rax, QWORD PTR [r10+368]
+ mov r8, QWORD PTR [rcx+632]
+ mov QWORD PTR [rcx+624], rax
+ adc r8, QWORD PTR [r10+376]
+ mov rax, QWORD PTR [rcx+640]
+ mov QWORD PTR [rcx+632], r8
+ adc rax, QWORD PTR [r10+384]
+ mov r8, QWORD PTR [rcx+648]
+ mov QWORD PTR [rcx+640], rax
+ adc r8, QWORD PTR [r10+392]
+ mov rax, QWORD PTR [rcx+656]
+ mov QWORD PTR [rcx+648], r8
+ adc rax, QWORD PTR [r10+400]
+ mov r8, QWORD PTR [rcx+664]
+ mov QWORD PTR [rcx+656], rax
+ adc r8, QWORD PTR [r10+408]
+ mov rax, QWORD PTR [rcx+672]
+ mov QWORD PTR [rcx+664], r8
+ adc rax, QWORD PTR [r10+416]
+ mov r8, QWORD PTR [rcx+680]
+ mov QWORD PTR [rcx+672], rax
+ adc r8, QWORD PTR [r10+424]
+ mov rax, QWORD PTR [rcx+688]
+ mov QWORD PTR [rcx+680], r8
+ adc rax, QWORD PTR [r10+432]
+ mov r8, QWORD PTR [rcx+696]
+ mov QWORD PTR [rcx+688], rax
+ adc r8, QWORD PTR [r10+440]
+ mov rax, QWORD PTR [rcx+704]
+ mov QWORD PTR [rcx+696], r8
+ adc rax, QWORD PTR [r10+448]
+ mov r8, QWORD PTR [rcx+712]
+ mov QWORD PTR [rcx+704], rax
+ adc r8, QWORD PTR [r10+456]
+ mov rax, QWORD PTR [rcx+720]
+ mov QWORD PTR [rcx+712], r8
+ adc rax, QWORD PTR [r10+464]
+ mov r8, QWORD PTR [rcx+728]
+ mov QWORD PTR [rcx+720], rax
+ adc r8, QWORD PTR [r10+472]
+ mov rax, QWORD PTR [rcx+736]
+ mov QWORD PTR [rcx+728], r8
+ adc rax, QWORD PTR [r10+480]
+ mov r8, QWORD PTR [rcx+744]
+ mov QWORD PTR [rcx+736], rax
+ adc r8, QWORD PTR [r10+488]
+ mov rax, QWORD PTR [rcx+752]
+ mov QWORD PTR [rcx+744], r8
+ adc rax, QWORD PTR [r10+496]
+ mov r8, QWORD PTR [rcx+760]
+ mov QWORD PTR [rcx+752], rax
+ adc r8, QWORD PTR [r10+504]
+ mov QWORD PTR [rcx+760], r8
+ adc r9, 0
+ mov QWORD PTR [rcx+768], r9
+ ; Add in place
+ mov rax, QWORD PTR [rcx+512]
+ xor r9, r9
+ add rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rcx+520]
+ mov QWORD PTR [rcx+512], rax
+ adc r8, QWORD PTR [rdx+8]
+ mov rax, QWORD PTR [rcx+528]
+ mov QWORD PTR [rcx+520], r8
+ adc rax, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rcx+536]
+ mov QWORD PTR [rcx+528], rax
+ adc r8, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rcx+544]
+ mov QWORD PTR [rcx+536], r8
+ adc rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rcx+552]
+ mov QWORD PTR [rcx+544], rax
+ adc r8, QWORD PTR [rdx+40]
+ mov rax, QWORD PTR [rcx+560]
+ mov QWORD PTR [rcx+552], r8
+ adc rax, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rcx+568]
+ mov QWORD PTR [rcx+560], rax
+ adc r8, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rcx+576]
+ mov QWORD PTR [rcx+568], r8
+ adc rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rcx+584]
+ mov QWORD PTR [rcx+576], rax
+ adc r8, QWORD PTR [rdx+72]
+ mov rax, QWORD PTR [rcx+592]
+ mov QWORD PTR [rcx+584], r8
+ adc rax, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rcx+600]
+ mov QWORD PTR [rcx+592], rax
+ adc r8, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rcx+608]
+ mov QWORD PTR [rcx+600], r8
+ adc rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rcx+616]
+ mov QWORD PTR [rcx+608], rax
+ adc r8, QWORD PTR [rdx+104]
+ mov rax, QWORD PTR [rcx+624]
+ mov QWORD PTR [rcx+616], r8
+ adc rax, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rcx+632]
+ mov QWORD PTR [rcx+624], rax
+ adc r8, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rcx+640]
+ mov QWORD PTR [rcx+632], r8
+ adc rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rcx+648]
+ mov QWORD PTR [rcx+640], rax
+ adc r8, QWORD PTR [rdx+136]
+ mov rax, QWORD PTR [rcx+656]
+ mov QWORD PTR [rcx+648], r8
+ adc rax, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rcx+664]
+ mov QWORD PTR [rcx+656], rax
+ adc r8, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [rcx+672]
+ mov QWORD PTR [rcx+664], r8
+ adc rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rcx+680]
+ mov QWORD PTR [rcx+672], rax
+ adc r8, QWORD PTR [rdx+168]
+ mov rax, QWORD PTR [rcx+688]
+ mov QWORD PTR [rcx+680], r8
+ adc rax, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rcx+696]
+ mov QWORD PTR [rcx+688], rax
+ adc r8, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [rcx+704]
+ mov QWORD PTR [rcx+696], r8
+ adc rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rcx+712]
+ mov QWORD PTR [rcx+704], rax
+ adc r8, QWORD PTR [rdx+200]
+ mov rax, QWORD PTR [rcx+720]
+ mov QWORD PTR [rcx+712], r8
+ adc rax, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rcx+728]
+ mov QWORD PTR [rcx+720], rax
+ adc r8, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [rcx+736]
+ mov QWORD PTR [rcx+728], r8
+ adc rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rcx+744]
+ mov QWORD PTR [rcx+736], rax
+ adc r8, QWORD PTR [rdx+232]
+ mov rax, QWORD PTR [rcx+752]
+ mov QWORD PTR [rcx+744], r8
+ adc rax, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rcx+760]
+ mov QWORD PTR [rcx+752], rax
+ adc r8, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [rcx+768]
+ mov QWORD PTR [rcx+760], r8
+ adc rax, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+768], rax
+ adc r9, 0
+ ; Add to zero
+ mov rax, QWORD PTR [rdx+264]
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+776], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+784], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+792], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+800], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+808], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+816], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+824], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+832], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+840], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+848], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+856], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+864], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+872], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+880], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+384]
+ mov QWORD PTR [rcx+888], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+392]
+ mov QWORD PTR [rcx+896], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+400]
+ mov QWORD PTR [rcx+904], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+408]
+ mov QWORD PTR [rcx+912], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+416]
+ mov QWORD PTR [rcx+920], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+424]
+ mov QWORD PTR [rcx+928], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+432]
+ mov QWORD PTR [rcx+936], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+440]
+ mov QWORD PTR [rcx+944], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+448]
+ mov QWORD PTR [rcx+952], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+456]
+ mov QWORD PTR [rcx+960], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+464]
+ mov QWORD PTR [rcx+968], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+472]
+ mov QWORD PTR [rcx+976], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+480]
+ mov QWORD PTR [rcx+984], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+488]
+ mov QWORD PTR [rcx+992], r8
+ adc rax, 0
+ mov r8, QWORD PTR [rdx+496]
+ mov QWORD PTR [rcx+1000], rax
+ adc r8, 0
+ mov rax, QWORD PTR [rdx+504]
+ mov QWORD PTR [rcx+1008], r8
+ adc rax, 0
+ mov QWORD PTR [rcx+1016], rax
+ add rsp, 1304
+ pop r12
+ ret
+sp_4096_sqr_avx2_64 ENDP
+_text ENDS
+ENDIF
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mul_d_64 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ mov QWORD PTR [rcx+120], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[16] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+128]
+ add r11, rax
+ mov QWORD PTR [rcx+128], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[17] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ add r12, rax
+ mov QWORD PTR [rcx+136], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[18] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ add r10, rax
+ mov QWORD PTR [rcx+144], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[19] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+152]
+ add r11, rax
+ mov QWORD PTR [rcx+152], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[20] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+160]
+ add r12, rax
+ mov QWORD PTR [rcx+160], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[21] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+168]
+ add r10, rax
+ mov QWORD PTR [rcx+168], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[22] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+176]
+ add r11, rax
+ mov QWORD PTR [rcx+176], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[23] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ add r12, rax
+ mov QWORD PTR [rcx+184], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[24] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ add r10, rax
+ mov QWORD PTR [rcx+192], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[25] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+200]
+ add r11, rax
+ mov QWORD PTR [rcx+200], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[26] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+208]
+ add r12, rax
+ mov QWORD PTR [rcx+208], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[27] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+216]
+ add r10, rax
+ mov QWORD PTR [rcx+216], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[28] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+224]
+ add r11, rax
+ mov QWORD PTR [rcx+224], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[29] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ add r12, rax
+ mov QWORD PTR [rcx+232], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[30] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ add r10, rax
+ mov QWORD PTR [rcx+240], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[31] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+248]
+ add r11, rax
+ mov QWORD PTR [rcx+248], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[32] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+256]
+ add r12, rax
+ mov QWORD PTR [rcx+256], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[33] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+264]
+ add r10, rax
+ mov QWORD PTR [rcx+264], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[34] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+272]
+ add r11, rax
+ mov QWORD PTR [rcx+272], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[35] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+280]
+ add r12, rax
+ mov QWORD PTR [rcx+280], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[36] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+288]
+ add r10, rax
+ mov QWORD PTR [rcx+288], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[37] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+296]
+ add r11, rax
+ mov QWORD PTR [rcx+296], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[38] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+304]
+ add r12, rax
+ mov QWORD PTR [rcx+304], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[39] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+312]
+ add r10, rax
+ mov QWORD PTR [rcx+312], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[40] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+320]
+ add r11, rax
+ mov QWORD PTR [rcx+320], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[41] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+328]
+ add r12, rax
+ mov QWORD PTR [rcx+328], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[42] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+336]
+ add r10, rax
+ mov QWORD PTR [rcx+336], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[43] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+344]
+ add r11, rax
+ mov QWORD PTR [rcx+344], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[44] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+352]
+ add r12, rax
+ mov QWORD PTR [rcx+352], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[45] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+360]
+ add r10, rax
+ mov QWORD PTR [rcx+360], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[46] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+368]
+ add r11, rax
+ mov QWORD PTR [rcx+368], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[47] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+376]
+ add r12, rax
+ mov QWORD PTR [rcx+376], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[48] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+384]
+ add r10, rax
+ mov QWORD PTR [rcx+384], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[49] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+392]
+ add r11, rax
+ mov QWORD PTR [rcx+392], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[50] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+400]
+ add r12, rax
+ mov QWORD PTR [rcx+400], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[51] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+408]
+ add r10, rax
+ mov QWORD PTR [rcx+408], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[52] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+416]
+ add r11, rax
+ mov QWORD PTR [rcx+416], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[53] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+424]
+ add r12, rax
+ mov QWORD PTR [rcx+424], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[54] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+432]
+ add r10, rax
+ mov QWORD PTR [rcx+432], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[55] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+440]
+ add r11, rax
+ mov QWORD PTR [rcx+440], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[56] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+448]
+ add r12, rax
+ mov QWORD PTR [rcx+448], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[57] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+456]
+ add r10, rax
+ mov QWORD PTR [rcx+456], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[58] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+464]
+ add r11, rax
+ mov QWORD PTR [rcx+464], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[59] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+472]
+ add r12, rax
+ mov QWORD PTR [rcx+472], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[60] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+480]
+ add r10, rax
+ mov QWORD PTR [rcx+480], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[61] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+488]
+ add r11, rax
+ mov QWORD PTR [rcx+488], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[62] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+496]
+ add r12, rax
+ mov QWORD PTR [rcx+496], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[63] * B
+ mov rax, r8
+ mul QWORD PTR [r9+504]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+504], r10
+ mov QWORD PTR [rcx+512], r11
+ pop r12
+ ret
+sp_4096_mul_d_64 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_cond_sub_64 PROC
+ sub rsp, 512
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [r8+192]
+ mov r11, QWORD PTR [r8+200]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+192], r10
+ mov QWORD PTR [rsp+200], r11
+ mov r10, QWORD PTR [r8+208]
+ mov r11, QWORD PTR [r8+216]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+208], r10
+ mov QWORD PTR [rsp+216], r11
+ mov r10, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [r8+232]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+224], r10
+ mov QWORD PTR [rsp+232], r11
+ mov r10, QWORD PTR [r8+240]
+ mov r11, QWORD PTR [r8+248]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+240], r10
+ mov QWORD PTR [rsp+248], r11
+ mov r10, QWORD PTR [r8+256]
+ mov r11, QWORD PTR [r8+264]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+256], r10
+ mov QWORD PTR [rsp+264], r11
+ mov r10, QWORD PTR [r8+272]
+ mov r11, QWORD PTR [r8+280]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+272], r10
+ mov QWORD PTR [rsp+280], r11
+ mov r10, QWORD PTR [r8+288]
+ mov r11, QWORD PTR [r8+296]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+288], r10
+ mov QWORD PTR [rsp+296], r11
+ mov r10, QWORD PTR [r8+304]
+ mov r11, QWORD PTR [r8+312]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+304], r10
+ mov QWORD PTR [rsp+312], r11
+ mov r10, QWORD PTR [r8+320]
+ mov r11, QWORD PTR [r8+328]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+320], r10
+ mov QWORD PTR [rsp+328], r11
+ mov r10, QWORD PTR [r8+336]
+ mov r11, QWORD PTR [r8+344]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+336], r10
+ mov QWORD PTR [rsp+344], r11
+ mov r10, QWORD PTR [r8+352]
+ mov r11, QWORD PTR [r8+360]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+352], r10
+ mov QWORD PTR [rsp+360], r11
+ mov r10, QWORD PTR [r8+368]
+ mov r11, QWORD PTR [r8+376]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+368], r10
+ mov QWORD PTR [rsp+376], r11
+ mov r10, QWORD PTR [r8+384]
+ mov r11, QWORD PTR [r8+392]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+384], r10
+ mov QWORD PTR [rsp+392], r11
+ mov r10, QWORD PTR [r8+400]
+ mov r11, QWORD PTR [r8+408]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+400], r10
+ mov QWORD PTR [rsp+408], r11
+ mov r10, QWORD PTR [r8+416]
+ mov r11, QWORD PTR [r8+424]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+416], r10
+ mov QWORD PTR [rsp+424], r11
+ mov r10, QWORD PTR [r8+432]
+ mov r11, QWORD PTR [r8+440]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+432], r10
+ mov QWORD PTR [rsp+440], r11
+ mov r10, QWORD PTR [r8+448]
+ mov r11, QWORD PTR [r8+456]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+448], r10
+ mov QWORD PTR [rsp+456], r11
+ mov r10, QWORD PTR [r8+464]
+ mov r11, QWORD PTR [r8+472]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+464], r10
+ mov QWORD PTR [rsp+472], r11
+ mov r10, QWORD PTR [r8+480]
+ mov r11, QWORD PTR [r8+488]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+480], r10
+ mov QWORD PTR [rsp+488], r11
+ mov r10, QWORD PTR [r8+496]
+ mov r11, QWORD PTR [r8+504]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+496], r10
+ mov QWORD PTR [rsp+504], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ sbb r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ sbb r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ sbb r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ sbb r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ sbb r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ sbb r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ sbb r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ sbb r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov r10, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rsp+192]
+ sbb r10, r8
+ mov QWORD PTR [rcx+184], r11
+ mov r11, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rsp+200]
+ sbb r11, r8
+ mov QWORD PTR [rcx+192], r10
+ mov r10, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rsp+208]
+ sbb r10, r8
+ mov QWORD PTR [rcx+200], r11
+ mov r11, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rsp+216]
+ sbb r11, r8
+ mov QWORD PTR [rcx+208], r10
+ mov r10, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rsp+224]
+ sbb r10, r8
+ mov QWORD PTR [rcx+216], r11
+ mov r11, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rsp+232]
+ sbb r11, r8
+ mov QWORD PTR [rcx+224], r10
+ mov r10, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rsp+240]
+ sbb r10, r8
+ mov QWORD PTR [rcx+232], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rsp+248]
+ sbb r11, r8
+ mov QWORD PTR [rcx+240], r10
+ mov r10, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [rsp+256]
+ sbb r10, r8
+ mov QWORD PTR [rcx+248], r11
+ mov r11, QWORD PTR [rdx+264]
+ mov r8, QWORD PTR [rsp+264]
+ sbb r11, r8
+ mov QWORD PTR [rcx+256], r10
+ mov r10, QWORD PTR [rdx+272]
+ mov r8, QWORD PTR [rsp+272]
+ sbb r10, r8
+ mov QWORD PTR [rcx+264], r11
+ mov r11, QWORD PTR [rdx+280]
+ mov r8, QWORD PTR [rsp+280]
+ sbb r11, r8
+ mov QWORD PTR [rcx+272], r10
+ mov r10, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [rsp+288]
+ sbb r10, r8
+ mov QWORD PTR [rcx+280], r11
+ mov r11, QWORD PTR [rdx+296]
+ mov r8, QWORD PTR [rsp+296]
+ sbb r11, r8
+ mov QWORD PTR [rcx+288], r10
+ mov r10, QWORD PTR [rdx+304]
+ mov r8, QWORD PTR [rsp+304]
+ sbb r10, r8
+ mov QWORD PTR [rcx+296], r11
+ mov r11, QWORD PTR [rdx+312]
+ mov r8, QWORD PTR [rsp+312]
+ sbb r11, r8
+ mov QWORD PTR [rcx+304], r10
+ mov r10, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [rsp+320]
+ sbb r10, r8
+ mov QWORD PTR [rcx+312], r11
+ mov r11, QWORD PTR [rdx+328]
+ mov r8, QWORD PTR [rsp+328]
+ sbb r11, r8
+ mov QWORD PTR [rcx+320], r10
+ mov r10, QWORD PTR [rdx+336]
+ mov r8, QWORD PTR [rsp+336]
+ sbb r10, r8
+ mov QWORD PTR [rcx+328], r11
+ mov r11, QWORD PTR [rdx+344]
+ mov r8, QWORD PTR [rsp+344]
+ sbb r11, r8
+ mov QWORD PTR [rcx+336], r10
+ mov r10, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [rsp+352]
+ sbb r10, r8
+ mov QWORD PTR [rcx+344], r11
+ mov r11, QWORD PTR [rdx+360]
+ mov r8, QWORD PTR [rsp+360]
+ sbb r11, r8
+ mov QWORD PTR [rcx+352], r10
+ mov r10, QWORD PTR [rdx+368]
+ mov r8, QWORD PTR [rsp+368]
+ sbb r10, r8
+ mov QWORD PTR [rcx+360], r11
+ mov r11, QWORD PTR [rdx+376]
+ mov r8, QWORD PTR [rsp+376]
+ sbb r11, r8
+ mov QWORD PTR [rcx+368], r10
+ mov r10, QWORD PTR [rdx+384]
+ mov r8, QWORD PTR [rsp+384]
+ sbb r10, r8
+ mov QWORD PTR [rcx+376], r11
+ mov r11, QWORD PTR [rdx+392]
+ mov r8, QWORD PTR [rsp+392]
+ sbb r11, r8
+ mov QWORD PTR [rcx+384], r10
+ mov r10, QWORD PTR [rdx+400]
+ mov r8, QWORD PTR [rsp+400]
+ sbb r10, r8
+ mov QWORD PTR [rcx+392], r11
+ mov r11, QWORD PTR [rdx+408]
+ mov r8, QWORD PTR [rsp+408]
+ sbb r11, r8
+ mov QWORD PTR [rcx+400], r10
+ mov r10, QWORD PTR [rdx+416]
+ mov r8, QWORD PTR [rsp+416]
+ sbb r10, r8
+ mov QWORD PTR [rcx+408], r11
+ mov r11, QWORD PTR [rdx+424]
+ mov r8, QWORD PTR [rsp+424]
+ sbb r11, r8
+ mov QWORD PTR [rcx+416], r10
+ mov r10, QWORD PTR [rdx+432]
+ mov r8, QWORD PTR [rsp+432]
+ sbb r10, r8
+ mov QWORD PTR [rcx+424], r11
+ mov r11, QWORD PTR [rdx+440]
+ mov r8, QWORD PTR [rsp+440]
+ sbb r11, r8
+ mov QWORD PTR [rcx+432], r10
+ mov r10, QWORD PTR [rdx+448]
+ mov r8, QWORD PTR [rsp+448]
+ sbb r10, r8
+ mov QWORD PTR [rcx+440], r11
+ mov r11, QWORD PTR [rdx+456]
+ mov r8, QWORD PTR [rsp+456]
+ sbb r11, r8
+ mov QWORD PTR [rcx+448], r10
+ mov r10, QWORD PTR [rdx+464]
+ mov r8, QWORD PTR [rsp+464]
+ sbb r10, r8
+ mov QWORD PTR [rcx+456], r11
+ mov r11, QWORD PTR [rdx+472]
+ mov r8, QWORD PTR [rsp+472]
+ sbb r11, r8
+ mov QWORD PTR [rcx+464], r10
+ mov r10, QWORD PTR [rdx+480]
+ mov r8, QWORD PTR [rsp+480]
+ sbb r10, r8
+ mov QWORD PTR [rcx+472], r11
+ mov r11, QWORD PTR [rdx+488]
+ mov r8, QWORD PTR [rsp+488]
+ sbb r11, r8
+ mov QWORD PTR [rcx+480], r10
+ mov r10, QWORD PTR [rdx+496]
+ mov r8, QWORD PTR [rsp+496]
+ sbb r10, r8
+ mov QWORD PTR [rcx+488], r11
+ mov r11, QWORD PTR [rdx+504]
+ mov r8, QWORD PTR [rsp+504]
+ sbb r11, r8
+ mov QWORD PTR [rcx+496], r10
+ mov QWORD PTR [rcx+504], r11
+ sbb rax, 0
+ add rsp, 512
+ ret
+sp_4096_cond_sub_64 ENDP
+_text ENDS
+; /* Reduce the number back to 4096 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mont_reduce_64 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 64
+ mov r10, 64
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_4096_mont_loop_64:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc r11, 0
+ ; a[i+16] += m[16] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+128]
+ mov r14, QWORD PTR [rcx+128]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+128], r14
+ adc r12, 0
+ ; a[i+17] += m[17] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+136]
+ mov r14, QWORD PTR [rcx+136]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+136], r14
+ adc r11, 0
+ ; a[i+18] += m[18] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+144]
+ mov r14, QWORD PTR [rcx+144]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+144], r14
+ adc r12, 0
+ ; a[i+19] += m[19] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+152]
+ mov r14, QWORD PTR [rcx+152]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+152], r14
+ adc r11, 0
+ ; a[i+20] += m[20] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+160]
+ mov r14, QWORD PTR [rcx+160]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+160], r14
+ adc r12, 0
+ ; a[i+21] += m[21] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+168]
+ mov r14, QWORD PTR [rcx+168]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+168], r14
+ adc r11, 0
+ ; a[i+22] += m[22] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+176]
+ mov r14, QWORD PTR [rcx+176]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+176], r14
+ adc r12, 0
+ ; a[i+23] += m[23] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+184]
+ mov r14, QWORD PTR [rcx+184]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+184], r14
+ adc r11, 0
+ ; a[i+24] += m[24] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+192]
+ mov r14, QWORD PTR [rcx+192]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+192], r14
+ adc r12, 0
+ ; a[i+25] += m[25] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+200]
+ mov r14, QWORD PTR [rcx+200]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+200], r14
+ adc r11, 0
+ ; a[i+26] += m[26] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+208]
+ mov r14, QWORD PTR [rcx+208]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+208], r14
+ adc r12, 0
+ ; a[i+27] += m[27] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+216]
+ mov r14, QWORD PTR [rcx+216]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+216], r14
+ adc r11, 0
+ ; a[i+28] += m[28] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+224]
+ mov r14, QWORD PTR [rcx+224]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+224], r14
+ adc r12, 0
+ ; a[i+29] += m[29] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+232]
+ mov r14, QWORD PTR [rcx+232]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+232], r14
+ adc r11, 0
+ ; a[i+30] += m[30] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+240]
+ mov r14, QWORD PTR [rcx+240]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+240], r14
+ adc r12, 0
+ ; a[i+31] += m[31] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+248]
+ mov r14, QWORD PTR [rcx+248]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+248], r14
+ adc r11, 0
+ ; a[i+32] += m[32] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+256]
+ mov r14, QWORD PTR [rcx+256]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+256], r14
+ adc r12, 0
+ ; a[i+33] += m[33] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+264]
+ mov r14, QWORD PTR [rcx+264]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+264], r14
+ adc r11, 0
+ ; a[i+34] += m[34] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+272]
+ mov r14, QWORD PTR [rcx+272]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+272], r14
+ adc r12, 0
+ ; a[i+35] += m[35] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+280]
+ mov r14, QWORD PTR [rcx+280]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+280], r14
+ adc r11, 0
+ ; a[i+36] += m[36] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+288]
+ mov r14, QWORD PTR [rcx+288]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+288], r14
+ adc r12, 0
+ ; a[i+37] += m[37] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+296]
+ mov r14, QWORD PTR [rcx+296]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+296], r14
+ adc r11, 0
+ ; a[i+38] += m[38] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+304]
+ mov r14, QWORD PTR [rcx+304]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+304], r14
+ adc r12, 0
+ ; a[i+39] += m[39] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+312]
+ mov r14, QWORD PTR [rcx+312]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+312], r14
+ adc r11, 0
+ ; a[i+40] += m[40] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+320]
+ mov r14, QWORD PTR [rcx+320]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+320], r14
+ adc r12, 0
+ ; a[i+41] += m[41] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+328]
+ mov r14, QWORD PTR [rcx+328]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+328], r14
+ adc r11, 0
+ ; a[i+42] += m[42] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+336]
+ mov r14, QWORD PTR [rcx+336]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+336], r14
+ adc r12, 0
+ ; a[i+43] += m[43] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+344]
+ mov r14, QWORD PTR [rcx+344]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+344], r14
+ adc r11, 0
+ ; a[i+44] += m[44] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+352]
+ mov r14, QWORD PTR [rcx+352]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+352], r14
+ adc r12, 0
+ ; a[i+45] += m[45] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+360]
+ mov r14, QWORD PTR [rcx+360]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+360], r14
+ adc r11, 0
+ ; a[i+46] += m[46] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+368]
+ mov r14, QWORD PTR [rcx+368]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+368], r14
+ adc r12, 0
+ ; a[i+47] += m[47] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+376]
+ mov r14, QWORD PTR [rcx+376]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+376], r14
+ adc r11, 0
+ ; a[i+48] += m[48] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+384]
+ mov r14, QWORD PTR [rcx+384]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+384], r14
+ adc r12, 0
+ ; a[i+49] += m[49] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+392]
+ mov r14, QWORD PTR [rcx+392]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+392], r14
+ adc r11, 0
+ ; a[i+50] += m[50] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+400]
+ mov r14, QWORD PTR [rcx+400]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+400], r14
+ adc r12, 0
+ ; a[i+51] += m[51] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+408]
+ mov r14, QWORD PTR [rcx+408]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+408], r14
+ adc r11, 0
+ ; a[i+52] += m[52] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+416]
+ mov r14, QWORD PTR [rcx+416]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+416], r14
+ adc r12, 0
+ ; a[i+53] += m[53] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+424]
+ mov r14, QWORD PTR [rcx+424]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+424], r14
+ adc r11, 0
+ ; a[i+54] += m[54] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+432]
+ mov r14, QWORD PTR [rcx+432]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+432], r14
+ adc r12, 0
+ ; a[i+55] += m[55] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+440]
+ mov r14, QWORD PTR [rcx+440]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+440], r14
+ adc r11, 0
+ ; a[i+56] += m[56] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+448]
+ mov r14, QWORD PTR [rcx+448]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+448], r14
+ adc r12, 0
+ ; a[i+57] += m[57] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+456]
+ mov r14, QWORD PTR [rcx+456]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+456], r14
+ adc r11, 0
+ ; a[i+58] += m[58] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+464]
+ mov r14, QWORD PTR [rcx+464]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+464], r14
+ adc r12, 0
+ ; a[i+59] += m[59] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+472]
+ mov r14, QWORD PTR [rcx+472]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+472], r14
+ adc r11, 0
+ ; a[i+60] += m[60] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+480]
+ mov r14, QWORD PTR [rcx+480]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+480], r14
+ adc r12, 0
+ ; a[i+61] += m[61] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+488]
+ mov r14, QWORD PTR [rcx+488]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+488], r14
+ adc r11, 0
+ ; a[i+62] += m[62] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+496]
+ mov r14, QWORD PTR [rcx+496]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+496], r14
+ adc r12, 0
+ ; a[i+63] += m[63] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+504]
+ mov r14, QWORD PTR [rcx+504]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+504], r14
+ adc QWORD PTR [rcx+512], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_4096_mont_loop_64
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 512
+ call sp_4096_cond_sub_64
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_4096_mont_reduce_64 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_cond_sub_avx2_64 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+192]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+184], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+200]
+ mov r11, QWORD PTR [rdx+200]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+192], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+208]
+ mov r12, QWORD PTR [rdx+208]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+200], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+216]
+ mov r10, QWORD PTR [rdx+216]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+208], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [rdx+224]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+216], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+232]
+ mov r12, QWORD PTR [rdx+232]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+224], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+240]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+232], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+248]
+ mov r11, QWORD PTR [rdx+248]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+240], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+256]
+ mov r12, QWORD PTR [rdx+256]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+248], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+264]
+ mov r10, QWORD PTR [rdx+264]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+256], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+272]
+ mov r11, QWORD PTR [rdx+272]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+264], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+280]
+ mov r12, QWORD PTR [rdx+280]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+272], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+288]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+280], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+296]
+ mov r11, QWORD PTR [rdx+296]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+288], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+304]
+ mov r12, QWORD PTR [rdx+304]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+296], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+312]
+ mov r10, QWORD PTR [rdx+312]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+304], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+320]
+ mov r11, QWORD PTR [rdx+320]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+312], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+328]
+ mov r12, QWORD PTR [rdx+328]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+320], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+336]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+328], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+344]
+ mov r11, QWORD PTR [rdx+344]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+336], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+352]
+ mov r12, QWORD PTR [rdx+352]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+344], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+360]
+ mov r10, QWORD PTR [rdx+360]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+352], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+368]
+ mov r11, QWORD PTR [rdx+368]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+360], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+376]
+ mov r12, QWORD PTR [rdx+376]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+368], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+384]
+ mov r10, QWORD PTR [rdx+384]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+376], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+392]
+ mov r11, QWORD PTR [rdx+392]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+384], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+400]
+ mov r12, QWORD PTR [rdx+400]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+392], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+408]
+ mov r10, QWORD PTR [rdx+408]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+400], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+416]
+ mov r11, QWORD PTR [rdx+416]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+408], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+424]
+ mov r12, QWORD PTR [rdx+424]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+416], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+432]
+ mov r10, QWORD PTR [rdx+432]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+424], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+440]
+ mov r11, QWORD PTR [rdx+440]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+432], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+448]
+ mov r12, QWORD PTR [rdx+448]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+440], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+456]
+ mov r10, QWORD PTR [rdx+456]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+448], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+464]
+ mov r11, QWORD PTR [rdx+464]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+456], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+472]
+ mov r12, QWORD PTR [rdx+472]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+464], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+480]
+ mov r10, QWORD PTR [rdx+480]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+472], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+488]
+ mov r11, QWORD PTR [rdx+488]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+480], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+496]
+ mov r12, QWORD PTR [rdx+496]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+488], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+504]
+ mov r10, QWORD PTR [rdx+504]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+496], r12
+ sbb r10, r11
+ mov QWORD PTR [rcx+504], r10
+ sbb rax, 0
+ pop r12
+ ret
+sp_4096_cond_sub_avx2_64 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mul_d_avx2_64 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+120], r12
+ ; A[16] * B
+ mulx r10, r9, QWORD PTR [rax+128]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+128], r11
+ ; A[17] * B
+ mulx r10, r9, QWORD PTR [rax+136]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+136], r12
+ ; A[18] * B
+ mulx r10, r9, QWORD PTR [rax+144]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+144], r11
+ ; A[19] * B
+ mulx r10, r9, QWORD PTR [rax+152]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+152], r12
+ ; A[20] * B
+ mulx r10, r9, QWORD PTR [rax+160]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+160], r11
+ ; A[21] * B
+ mulx r10, r9, QWORD PTR [rax+168]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+168], r12
+ ; A[22] * B
+ mulx r10, r9, QWORD PTR [rax+176]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+176], r11
+ ; A[23] * B
+ mulx r10, r9, QWORD PTR [rax+184]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+184], r12
+ ; A[24] * B
+ mulx r10, r9, QWORD PTR [rax+192]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+192], r11
+ ; A[25] * B
+ mulx r10, r9, QWORD PTR [rax+200]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+200], r12
+ ; A[26] * B
+ mulx r10, r9, QWORD PTR [rax+208]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+208], r11
+ ; A[27] * B
+ mulx r10, r9, QWORD PTR [rax+216]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+216], r12
+ ; A[28] * B
+ mulx r10, r9, QWORD PTR [rax+224]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+224], r11
+ ; A[29] * B
+ mulx r10, r9, QWORD PTR [rax+232]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+232], r12
+ ; A[30] * B
+ mulx r10, r9, QWORD PTR [rax+240]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+240], r11
+ ; A[31] * B
+ mulx r10, r9, QWORD PTR [rax+248]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+248], r12
+ ; A[32] * B
+ mulx r10, r9, QWORD PTR [rax+256]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+256], r11
+ ; A[33] * B
+ mulx r10, r9, QWORD PTR [rax+264]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+264], r12
+ ; A[34] * B
+ mulx r10, r9, QWORD PTR [rax+272]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+272], r11
+ ; A[35] * B
+ mulx r10, r9, QWORD PTR [rax+280]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+280], r12
+ ; A[36] * B
+ mulx r10, r9, QWORD PTR [rax+288]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+288], r11
+ ; A[37] * B
+ mulx r10, r9, QWORD PTR [rax+296]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+296], r12
+ ; A[38] * B
+ mulx r10, r9, QWORD PTR [rax+304]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+304], r11
+ ; A[39] * B
+ mulx r10, r9, QWORD PTR [rax+312]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+312], r12
+ ; A[40] * B
+ mulx r10, r9, QWORD PTR [rax+320]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+320], r11
+ ; A[41] * B
+ mulx r10, r9, QWORD PTR [rax+328]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+328], r12
+ ; A[42] * B
+ mulx r10, r9, QWORD PTR [rax+336]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+336], r11
+ ; A[43] * B
+ mulx r10, r9, QWORD PTR [rax+344]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+344], r12
+ ; A[44] * B
+ mulx r10, r9, QWORD PTR [rax+352]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+352], r11
+ ; A[45] * B
+ mulx r10, r9, QWORD PTR [rax+360]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+360], r12
+ ; A[46] * B
+ mulx r10, r9, QWORD PTR [rax+368]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+368], r11
+ ; A[47] * B
+ mulx r10, r9, QWORD PTR [rax+376]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+376], r12
+ ; A[48] * B
+ mulx r10, r9, QWORD PTR [rax+384]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+384], r11
+ ; A[49] * B
+ mulx r10, r9, QWORD PTR [rax+392]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+392], r12
+ ; A[50] * B
+ mulx r10, r9, QWORD PTR [rax+400]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+400], r11
+ ; A[51] * B
+ mulx r10, r9, QWORD PTR [rax+408]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+408], r12
+ ; A[52] * B
+ mulx r10, r9, QWORD PTR [rax+416]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+416], r11
+ ; A[53] * B
+ mulx r10, r9, QWORD PTR [rax+424]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+424], r12
+ ; A[54] * B
+ mulx r10, r9, QWORD PTR [rax+432]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+432], r11
+ ; A[55] * B
+ mulx r10, r9, QWORD PTR [rax+440]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+440], r12
+ ; A[56] * B
+ mulx r10, r9, QWORD PTR [rax+448]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+448], r11
+ ; A[57] * B
+ mulx r10, r9, QWORD PTR [rax+456]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+456], r12
+ ; A[58] * B
+ mulx r10, r9, QWORD PTR [rax+464]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+464], r11
+ ; A[59] * B
+ mulx r10, r9, QWORD PTR [rax+472]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+472], r12
+ ; A[60] * B
+ mulx r10, r9, QWORD PTR [rax+480]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+480], r11
+ ; A[61] * B
+ mulx r10, r9, QWORD PTR [rax+488]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+488], r12
+ ; A[62] * B
+ mulx r10, r9, QWORD PTR [rax+496]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+496], r11
+ ; A[63] * B
+ mulx r10, r9, QWORD PTR [rax+504]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+504], r12
+ mov QWORD PTR [rcx+512], r11
+ pop r13
+ pop r12
+ ret
+sp_4096_mul_d_avx2_64 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_4096_word_asm_64 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_4096_word_asm_64 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_cmp_64 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+504]
+ mov r12, QWORD PTR [rdx+504]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+496]
+ mov r12, QWORD PTR [rdx+496]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+488]
+ mov r12, QWORD PTR [rdx+488]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+480]
+ mov r12, QWORD PTR [rdx+480]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+472]
+ mov r12, QWORD PTR [rdx+472]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+464]
+ mov r12, QWORD PTR [rdx+464]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+456]
+ mov r12, QWORD PTR [rdx+456]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+448]
+ mov r12, QWORD PTR [rdx+448]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+440]
+ mov r12, QWORD PTR [rdx+440]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+432]
+ mov r12, QWORD PTR [rdx+432]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+424]
+ mov r12, QWORD PTR [rdx+424]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+416]
+ mov r12, QWORD PTR [rdx+416]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+408]
+ mov r12, QWORD PTR [rdx+408]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+400]
+ mov r12, QWORD PTR [rdx+400]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+392]
+ mov r12, QWORD PTR [rdx+392]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+384]
+ mov r12, QWORD PTR [rdx+384]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+376]
+ mov r12, QWORD PTR [rdx+376]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+368]
+ mov r12, QWORD PTR [rdx+368]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+360]
+ mov r12, QWORD PTR [rdx+360]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+352]
+ mov r12, QWORD PTR [rdx+352]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+344]
+ mov r12, QWORD PTR [rdx+344]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+336]
+ mov r12, QWORD PTR [rdx+336]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+328]
+ mov r12, QWORD PTR [rdx+328]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+320]
+ mov r12, QWORD PTR [rdx+320]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+312]
+ mov r12, QWORD PTR [rdx+312]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+304]
+ mov r12, QWORD PTR [rdx+304]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+296]
+ mov r12, QWORD PTR [rdx+296]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+288]
+ mov r12, QWORD PTR [rdx+288]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+280]
+ mov r12, QWORD PTR [rdx+280]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+272]
+ mov r12, QWORD PTR [rdx+272]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+264]
+ mov r12, QWORD PTR [rdx+264]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+256]
+ mov r12, QWORD PTR [rdx+256]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+248]
+ mov r12, QWORD PTR [rdx+248]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+240]
+ mov r12, QWORD PTR [rdx+240]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+232]
+ mov r12, QWORD PTR [rdx+232]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+224]
+ mov r12, QWORD PTR [rdx+224]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+216]
+ mov r12, QWORD PTR [rdx+216]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+208]
+ mov r12, QWORD PTR [rdx+208]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+200]
+ mov r12, QWORD PTR [rdx+200]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+192]
+ mov r12, QWORD PTR [rdx+192]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+184]
+ mov r12, QWORD PTR [rdx+184]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+176]
+ mov r12, QWORD PTR [rdx+176]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+168]
+ mov r12, QWORD PTR [rdx+168]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+160]
+ mov r12, QWORD PTR [rdx+160]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+152]
+ mov r12, QWORD PTR [rdx+152]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+144]
+ mov r12, QWORD PTR [rdx+144]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+136]
+ mov r12, QWORD PTR [rdx+136]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+128]
+ mov r12, QWORD PTR [rdx+128]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_4096_cmp_64 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_sub_64 PROC
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ sub r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ sbb r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ sbb r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ sbb r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ sbb r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ sbb r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ sbb r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ sbb r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ sbb r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ sbb r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ sbb r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ sbb r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ sbb r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ sbb r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ sbb r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ sbb r10, QWORD PTR [r8+120]
+ mov r9, QWORD PTR [rdx+128]
+ mov QWORD PTR [rcx+120], r10
+ sbb r9, QWORD PTR [r8+128]
+ mov r10, QWORD PTR [rdx+136]
+ mov QWORD PTR [rcx+128], r9
+ sbb r10, QWORD PTR [r8+136]
+ mov r9, QWORD PTR [rdx+144]
+ mov QWORD PTR [rcx+136], r10
+ sbb r9, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+152]
+ mov QWORD PTR [rcx+144], r9
+ sbb r10, QWORD PTR [r8+152]
+ mov r9, QWORD PTR [rdx+160]
+ mov QWORD PTR [rcx+152], r10
+ sbb r9, QWORD PTR [r8+160]
+ mov r10, QWORD PTR [rdx+168]
+ mov QWORD PTR [rcx+160], r9
+ sbb r10, QWORD PTR [r8+168]
+ mov r9, QWORD PTR [rdx+176]
+ mov QWORD PTR [rcx+168], r10
+ sbb r9, QWORD PTR [r8+176]
+ mov r10, QWORD PTR [rdx+184]
+ mov QWORD PTR [rcx+176], r9
+ sbb r10, QWORD PTR [r8+184]
+ mov r9, QWORD PTR [rdx+192]
+ mov QWORD PTR [rcx+184], r10
+ sbb r9, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+200]
+ mov QWORD PTR [rcx+192], r9
+ sbb r10, QWORD PTR [r8+200]
+ mov r9, QWORD PTR [rdx+208]
+ mov QWORD PTR [rcx+200], r10
+ sbb r9, QWORD PTR [r8+208]
+ mov r10, QWORD PTR [rdx+216]
+ mov QWORD PTR [rcx+208], r9
+ sbb r10, QWORD PTR [r8+216]
+ mov r9, QWORD PTR [rdx+224]
+ mov QWORD PTR [rcx+216], r10
+ sbb r9, QWORD PTR [r8+224]
+ mov r10, QWORD PTR [rdx+232]
+ mov QWORD PTR [rcx+224], r9
+ sbb r10, QWORD PTR [r8+232]
+ mov r9, QWORD PTR [rdx+240]
+ mov QWORD PTR [rcx+232], r10
+ sbb r9, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+248]
+ mov QWORD PTR [rcx+240], r9
+ sbb r10, QWORD PTR [r8+248]
+ mov r9, QWORD PTR [rdx+256]
+ mov QWORD PTR [rcx+248], r10
+ sbb r9, QWORD PTR [r8+256]
+ mov r10, QWORD PTR [rdx+264]
+ mov QWORD PTR [rcx+256], r9
+ sbb r10, QWORD PTR [r8+264]
+ mov r9, QWORD PTR [rdx+272]
+ mov QWORD PTR [rcx+264], r10
+ sbb r9, QWORD PTR [r8+272]
+ mov r10, QWORD PTR [rdx+280]
+ mov QWORD PTR [rcx+272], r9
+ sbb r10, QWORD PTR [r8+280]
+ mov r9, QWORD PTR [rdx+288]
+ mov QWORD PTR [rcx+280], r10
+ sbb r9, QWORD PTR [r8+288]
+ mov r10, QWORD PTR [rdx+296]
+ mov QWORD PTR [rcx+288], r9
+ sbb r10, QWORD PTR [r8+296]
+ mov r9, QWORD PTR [rdx+304]
+ mov QWORD PTR [rcx+296], r10
+ sbb r9, QWORD PTR [r8+304]
+ mov r10, QWORD PTR [rdx+312]
+ mov QWORD PTR [rcx+304], r9
+ sbb r10, QWORD PTR [r8+312]
+ mov r9, QWORD PTR [rdx+320]
+ mov QWORD PTR [rcx+312], r10
+ sbb r9, QWORD PTR [r8+320]
+ mov r10, QWORD PTR [rdx+328]
+ mov QWORD PTR [rcx+320], r9
+ sbb r10, QWORD PTR [r8+328]
+ mov r9, QWORD PTR [rdx+336]
+ mov QWORD PTR [rcx+328], r10
+ sbb r9, QWORD PTR [r8+336]
+ mov r10, QWORD PTR [rdx+344]
+ mov QWORD PTR [rcx+336], r9
+ sbb r10, QWORD PTR [r8+344]
+ mov r9, QWORD PTR [rdx+352]
+ mov QWORD PTR [rcx+344], r10
+ sbb r9, QWORD PTR [r8+352]
+ mov r10, QWORD PTR [rdx+360]
+ mov QWORD PTR [rcx+352], r9
+ sbb r10, QWORD PTR [r8+360]
+ mov r9, QWORD PTR [rdx+368]
+ mov QWORD PTR [rcx+360], r10
+ sbb r9, QWORD PTR [r8+368]
+ mov r10, QWORD PTR [rdx+376]
+ mov QWORD PTR [rcx+368], r9
+ sbb r10, QWORD PTR [r8+376]
+ mov r9, QWORD PTR [rdx+384]
+ mov QWORD PTR [rcx+376], r10
+ sbb r9, QWORD PTR [r8+384]
+ mov r10, QWORD PTR [rdx+392]
+ mov QWORD PTR [rcx+384], r9
+ sbb r10, QWORD PTR [r8+392]
+ mov r9, QWORD PTR [rdx+400]
+ mov QWORD PTR [rcx+392], r10
+ sbb r9, QWORD PTR [r8+400]
+ mov r10, QWORD PTR [rdx+408]
+ mov QWORD PTR [rcx+400], r9
+ sbb r10, QWORD PTR [r8+408]
+ mov r9, QWORD PTR [rdx+416]
+ mov QWORD PTR [rcx+408], r10
+ sbb r9, QWORD PTR [r8+416]
+ mov r10, QWORD PTR [rdx+424]
+ mov QWORD PTR [rcx+416], r9
+ sbb r10, QWORD PTR [r8+424]
+ mov r9, QWORD PTR [rdx+432]
+ mov QWORD PTR [rcx+424], r10
+ sbb r9, QWORD PTR [r8+432]
+ mov r10, QWORD PTR [rdx+440]
+ mov QWORD PTR [rcx+432], r9
+ sbb r10, QWORD PTR [r8+440]
+ mov r9, QWORD PTR [rdx+448]
+ mov QWORD PTR [rcx+440], r10
+ sbb r9, QWORD PTR [r8+448]
+ mov r10, QWORD PTR [rdx+456]
+ mov QWORD PTR [rcx+448], r9
+ sbb r10, QWORD PTR [r8+456]
+ mov r9, QWORD PTR [rdx+464]
+ mov QWORD PTR [rcx+456], r10
+ sbb r9, QWORD PTR [r8+464]
+ mov r10, QWORD PTR [rdx+472]
+ mov QWORD PTR [rcx+464], r9
+ sbb r10, QWORD PTR [r8+472]
+ mov r9, QWORD PTR [rdx+480]
+ mov QWORD PTR [rcx+472], r10
+ sbb r9, QWORD PTR [r8+480]
+ mov r10, QWORD PTR [rdx+488]
+ mov QWORD PTR [rcx+480], r9
+ sbb r10, QWORD PTR [r8+488]
+ mov r9, QWORD PTR [rdx+496]
+ mov QWORD PTR [rcx+488], r10
+ sbb r9, QWORD PTR [r8+496]
+ mov r10, QWORD PTR [rdx+504]
+ mov QWORD PTR [rcx+496], r9
+ sbb r10, QWORD PTR [r8+504]
+ mov QWORD PTR [rcx+504], r10
+ sbb rax, 0
+ ret
+sp_4096_sub_64 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 4096 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_mont_reduce_avx2_64 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 64
+ mov r11, 64
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 256
+ xor rbp, rbp
+L_4096_mont_loop_avx2_64:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-224]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-216]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-208]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-216], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-200]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-208], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+-192]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-200], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+-184]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-192], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+-176]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-184], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+-168]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-176], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+-160]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-168], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+-152]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-160], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+-144]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-152], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+-136]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-144], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+-128]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-136], r13
+ ; a[i+16] += m[16] * mu
+ mulx rcx, rax, QWORD PTR [r10+128]
+ mov r13, QWORD PTR [r9+-120]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-128], r12
+ ; a[i+17] += m[17] * mu
+ mulx rcx, rax, QWORD PTR [r10+136]
+ mov r12, QWORD PTR [r9+-112]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-120], r13
+ ; a[i+18] += m[18] * mu
+ mulx rcx, rax, QWORD PTR [r10+144]
+ mov r13, QWORD PTR [r9+-104]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-112], r12
+ ; a[i+19] += m[19] * mu
+ mulx rcx, rax, QWORD PTR [r10+152]
+ mov r12, QWORD PTR [r9+-96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-104], r13
+ ; a[i+20] += m[20] * mu
+ mulx rcx, rax, QWORD PTR [r10+160]
+ mov r13, QWORD PTR [r9+-88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-96], r12
+ ; a[i+21] += m[21] * mu
+ mulx rcx, rax, QWORD PTR [r10+168]
+ mov r12, QWORD PTR [r9+-80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-88], r13
+ ; a[i+22] += m[22] * mu
+ mulx rcx, rax, QWORD PTR [r10+176]
+ mov r13, QWORD PTR [r9+-72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-80], r12
+ ; a[i+23] += m[23] * mu
+ mulx rcx, rax, QWORD PTR [r10+184]
+ mov r12, QWORD PTR [r9+-64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-72], r13
+ ; a[i+24] += m[24] * mu
+ mulx rcx, rax, QWORD PTR [r10+192]
+ mov r13, QWORD PTR [r9+-56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-64], r12
+ ; a[i+25] += m[25] * mu
+ mulx rcx, rax, QWORD PTR [r10+200]
+ mov r12, QWORD PTR [r9+-48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-56], r13
+ ; a[i+26] += m[26] * mu
+ mulx rcx, rax, QWORD PTR [r10+208]
+ mov r13, QWORD PTR [r9+-40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-48], r12
+ ; a[i+27] += m[27] * mu
+ mulx rcx, rax, QWORD PTR [r10+216]
+ mov r12, QWORD PTR [r9+-32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-40], r13
+ ; a[i+28] += m[28] * mu
+ mulx rcx, rax, QWORD PTR [r10+224]
+ mov r13, QWORD PTR [r9+-24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-32], r12
+ ; a[i+29] += m[29] * mu
+ mulx rcx, rax, QWORD PTR [r10+232]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+30] += m[30] * mu
+ mulx rcx, rax, QWORD PTR [r10+240]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+31] += m[31] * mu
+ mulx rcx, rax, QWORD PTR [r10+248]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+32] += m[32] * mu
+ mulx rcx, rax, QWORD PTR [r10+256]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+33] += m[33] * mu
+ mulx rcx, rax, QWORD PTR [r10+264]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+34] += m[34] * mu
+ mulx rcx, rax, QWORD PTR [r10+272]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+35] += m[35] * mu
+ mulx rcx, rax, QWORD PTR [r10+280]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+36] += m[36] * mu
+ mulx rcx, rax, QWORD PTR [r10+288]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+37] += m[37] * mu
+ mulx rcx, rax, QWORD PTR [r10+296]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+38] += m[38] * mu
+ mulx rcx, rax, QWORD PTR [r10+304]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+39] += m[39] * mu
+ mulx rcx, rax, QWORD PTR [r10+312]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ ; a[i+40] += m[40] * mu
+ mulx rcx, rax, QWORD PTR [r10+320]
+ mov r13, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+64], r12
+ ; a[i+41] += m[41] * mu
+ mulx rcx, rax, QWORD PTR [r10+328]
+ mov r12, QWORD PTR [r9+80]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+72], r13
+ ; a[i+42] += m[42] * mu
+ mulx rcx, rax, QWORD PTR [r10+336]
+ mov r13, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+80], r12
+ ; a[i+43] += m[43] * mu
+ mulx rcx, rax, QWORD PTR [r10+344]
+ mov r12, QWORD PTR [r9+96]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+88], r13
+ ; a[i+44] += m[44] * mu
+ mulx rcx, rax, QWORD PTR [r10+352]
+ mov r13, QWORD PTR [r9+104]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+96], r12
+ ; a[i+45] += m[45] * mu
+ mulx rcx, rax, QWORD PTR [r10+360]
+ mov r12, QWORD PTR [r9+112]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+104], r13
+ ; a[i+46] += m[46] * mu
+ mulx rcx, rax, QWORD PTR [r10+368]
+ mov r13, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+112], r12
+ ; a[i+47] += m[47] * mu
+ mulx rcx, rax, QWORD PTR [r10+376]
+ mov r12, QWORD PTR [r9+128]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+120], r13
+ ; a[i+48] += m[48] * mu
+ mulx rcx, rax, QWORD PTR [r10+384]
+ mov r13, QWORD PTR [r9+136]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+128], r12
+ ; a[i+49] += m[49] * mu
+ mulx rcx, rax, QWORD PTR [r10+392]
+ mov r12, QWORD PTR [r9+144]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+136], r13
+ ; a[i+50] += m[50] * mu
+ mulx rcx, rax, QWORD PTR [r10+400]
+ mov r13, QWORD PTR [r9+152]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+144], r12
+ ; a[i+51] += m[51] * mu
+ mulx rcx, rax, QWORD PTR [r10+408]
+ mov r12, QWORD PTR [r9+160]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+152], r13
+ ; a[i+52] += m[52] * mu
+ mulx rcx, rax, QWORD PTR [r10+416]
+ mov r13, QWORD PTR [r9+168]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+160], r12
+ ; a[i+53] += m[53] * mu
+ mulx rcx, rax, QWORD PTR [r10+424]
+ mov r12, QWORD PTR [r9+176]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+168], r13
+ ; a[i+54] += m[54] * mu
+ mulx rcx, rax, QWORD PTR [r10+432]
+ mov r13, QWORD PTR [r9+184]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+176], r12
+ ; a[i+55] += m[55] * mu
+ mulx rcx, rax, QWORD PTR [r10+440]
+ mov r12, QWORD PTR [r9+192]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+184], r13
+ ; a[i+56] += m[56] * mu
+ mulx rcx, rax, QWORD PTR [r10+448]
+ mov r13, QWORD PTR [r9+200]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+192], r12
+ ; a[i+57] += m[57] * mu
+ mulx rcx, rax, QWORD PTR [r10+456]
+ mov r12, QWORD PTR [r9+208]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+200], r13
+ ; a[i+58] += m[58] * mu
+ mulx rcx, rax, QWORD PTR [r10+464]
+ mov r13, QWORD PTR [r9+216]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+208], r12
+ ; a[i+59] += m[59] * mu
+ mulx rcx, rax, QWORD PTR [r10+472]
+ mov r12, QWORD PTR [r9+224]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+216], r13
+ ; a[i+60] += m[60] * mu
+ mulx rcx, rax, QWORD PTR [r10+480]
+ mov r13, QWORD PTR [r9+232]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+224], r12
+ ; a[i+61] += m[61] * mu
+ mulx rcx, rax, QWORD PTR [r10+488]
+ mov r12, QWORD PTR [r9+240]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+232], r13
+ ; a[i+62] += m[62] * mu
+ mulx rcx, rax, QWORD PTR [r10+496]
+ mov r13, QWORD PTR [r9+248]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+240], r12
+ ; a[i+63] += m[63] * mu
+ mulx rcx, rax, QWORD PTR [r10+504]
+ mov r12, QWORD PTR [r9+256]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+248], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+256], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 1
+ add r9, 8
+ ; i -= 1
+ sub r11, 1
+ jnz L_4096_mont_loop_avx2_64
+ sub r9, 256
+ neg rbp
+ mov r8, r9
+ sub r9, 512
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+128]
+ mov rax, QWORD PTR [r8+128]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+120], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+136]
+ mov rcx, QWORD PTR [r8+136]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+128], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+144]
+ mov rdx, QWORD PTR [r8+144]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+136], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+152]
+ mov rax, QWORD PTR [r8+152]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+144], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+160]
+ mov rcx, QWORD PTR [r8+160]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+152], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+168]
+ mov rdx, QWORD PTR [r8+168]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+160], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+176]
+ mov rax, QWORD PTR [r8+176]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+168], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+184]
+ mov rcx, QWORD PTR [r8+184]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+176], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+192]
+ mov rdx, QWORD PTR [r8+192]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+184], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+200]
+ mov rax, QWORD PTR [r8+200]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+192], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+208]
+ mov rcx, QWORD PTR [r8+208]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+200], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+216]
+ mov rdx, QWORD PTR [r8+216]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+208], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+224]
+ mov rax, QWORD PTR [r8+224]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+216], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+232]
+ mov rcx, QWORD PTR [r8+232]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+224], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+240]
+ mov rdx, QWORD PTR [r8+240]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+232], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+248]
+ mov rax, QWORD PTR [r8+248]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+240], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+256]
+ mov rcx, QWORD PTR [r8+256]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+248], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+264]
+ mov rdx, QWORD PTR [r8+264]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+256], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+272]
+ mov rax, QWORD PTR [r8+272]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+264], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+280]
+ mov rcx, QWORD PTR [r8+280]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+272], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+288]
+ mov rdx, QWORD PTR [r8+288]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+280], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+296]
+ mov rax, QWORD PTR [r8+296]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+288], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+304]
+ mov rcx, QWORD PTR [r8+304]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+296], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+312]
+ mov rdx, QWORD PTR [r8+312]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+304], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+320]
+ mov rax, QWORD PTR [r8+320]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+312], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+328]
+ mov rcx, QWORD PTR [r8+328]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+320], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+336]
+ mov rdx, QWORD PTR [r8+336]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+328], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+344]
+ mov rax, QWORD PTR [r8+344]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+336], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+352]
+ mov rcx, QWORD PTR [r8+352]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+344], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+360]
+ mov rdx, QWORD PTR [r8+360]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+352], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+368]
+ mov rax, QWORD PTR [r8+368]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+360], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+376]
+ mov rcx, QWORD PTR [r8+376]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+368], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+384]
+ mov rdx, QWORD PTR [r8+384]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+376], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+392]
+ mov rax, QWORD PTR [r8+392]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+384], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+400]
+ mov rcx, QWORD PTR [r8+400]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+392], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+408]
+ mov rdx, QWORD PTR [r8+408]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+400], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+416]
+ mov rax, QWORD PTR [r8+416]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+408], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+424]
+ mov rcx, QWORD PTR [r8+424]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+416], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+432]
+ mov rdx, QWORD PTR [r8+432]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+424], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+440]
+ mov rax, QWORD PTR [r8+440]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+432], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+448]
+ mov rcx, QWORD PTR [r8+448]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+440], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+456]
+ mov rdx, QWORD PTR [r8+456]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+448], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+464]
+ mov rax, QWORD PTR [r8+464]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+456], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+472]
+ mov rcx, QWORD PTR [r8+472]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+464], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+480]
+ mov rdx, QWORD PTR [r8+480]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+472], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+488]
+ mov rax, QWORD PTR [r8+488]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+480], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+496]
+ mov rcx, QWORD PTR [r8+496]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+488], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+504]
+ mov rdx, QWORD PTR [r8+504]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+496], rcx
+ sbb rdx, rax
+ mov QWORD PTR [r9+504], rdx
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_4096_mont_reduce_avx2_64 ENDP
+_text ENDS
+ENDIF
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_cond_add_32 PROC
+ sub rsp, 256
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [r8+136]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+128], r10
+ mov QWORD PTR [rsp+136], r11
+ mov r10, QWORD PTR [r8+144]
+ mov r11, QWORD PTR [r8+152]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+144], r10
+ mov QWORD PTR [rsp+152], r11
+ mov r10, QWORD PTR [r8+160]
+ mov r11, QWORD PTR [r8+168]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+160], r10
+ mov QWORD PTR [rsp+168], r11
+ mov r10, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [r8+184]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+176], r10
+ mov QWORD PTR [rsp+184], r11
+ mov r10, QWORD PTR [r8+192]
+ mov r11, QWORD PTR [r8+200]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+192], r10
+ mov QWORD PTR [rsp+200], r11
+ mov r10, QWORD PTR [r8+208]
+ mov r11, QWORD PTR [r8+216]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+208], r10
+ mov QWORD PTR [rsp+216], r11
+ mov r10, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [r8+232]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+224], r10
+ mov QWORD PTR [rsp+232], r11
+ mov r10, QWORD PTR [r8+240]
+ mov r11, QWORD PTR [r8+248]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+240], r10
+ mov QWORD PTR [rsp+248], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ add r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ adc r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ adc r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ adc r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ adc r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ adc r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ adc r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ adc r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ adc r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ adc r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ adc r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ adc r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ adc r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ adc r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ adc r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ adc r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov r10, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rsp+128]
+ adc r10, r8
+ mov QWORD PTR [rcx+120], r11
+ mov r11, QWORD PTR [rdx+136]
+ mov r8, QWORD PTR [rsp+136]
+ adc r11, r8
+ mov QWORD PTR [rcx+128], r10
+ mov r10, QWORD PTR [rdx+144]
+ mov r8, QWORD PTR [rsp+144]
+ adc r10, r8
+ mov QWORD PTR [rcx+136], r11
+ mov r11, QWORD PTR [rdx+152]
+ mov r8, QWORD PTR [rsp+152]
+ adc r11, r8
+ mov QWORD PTR [rcx+144], r10
+ mov r10, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rsp+160]
+ adc r10, r8
+ mov QWORD PTR [rcx+152], r11
+ mov r11, QWORD PTR [rdx+168]
+ mov r8, QWORD PTR [rsp+168]
+ adc r11, r8
+ mov QWORD PTR [rcx+160], r10
+ mov r10, QWORD PTR [rdx+176]
+ mov r8, QWORD PTR [rsp+176]
+ adc r10, r8
+ mov QWORD PTR [rcx+168], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov r8, QWORD PTR [rsp+184]
+ adc r11, r8
+ mov QWORD PTR [rcx+176], r10
+ mov r10, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rsp+192]
+ adc r10, r8
+ mov QWORD PTR [rcx+184], r11
+ mov r11, QWORD PTR [rdx+200]
+ mov r8, QWORD PTR [rsp+200]
+ adc r11, r8
+ mov QWORD PTR [rcx+192], r10
+ mov r10, QWORD PTR [rdx+208]
+ mov r8, QWORD PTR [rsp+208]
+ adc r10, r8
+ mov QWORD PTR [rcx+200], r11
+ mov r11, QWORD PTR [rdx+216]
+ mov r8, QWORD PTR [rsp+216]
+ adc r11, r8
+ mov QWORD PTR [rcx+208], r10
+ mov r10, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rsp+224]
+ adc r10, r8
+ mov QWORD PTR [rcx+216], r11
+ mov r11, QWORD PTR [rdx+232]
+ mov r8, QWORD PTR [rsp+232]
+ adc r11, r8
+ mov QWORD PTR [rcx+224], r10
+ mov r10, QWORD PTR [rdx+240]
+ mov r8, QWORD PTR [rsp+240]
+ adc r10, r8
+ mov QWORD PTR [rcx+232], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov r8, QWORD PTR [rsp+248]
+ adc r11, r8
+ mov QWORD PTR [rcx+240], r10
+ mov QWORD PTR [rcx+248], r11
+ adc rax, 0
+ add rsp, 256
+ ret
+sp_4096_cond_add_32 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_cond_add_avx2_32 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ add r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+128]
+ mov r11, QWORD PTR [rdx+128]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+120], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+136]
+ mov r12, QWORD PTR [rdx+136]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+128], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+144]
+ mov r10, QWORD PTR [rdx+144]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+136], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+152]
+ mov r11, QWORD PTR [rdx+152]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+144], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+160]
+ mov r12, QWORD PTR [rdx+160]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+152], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+168]
+ mov r10, QWORD PTR [rdx+168]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+160], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+176]
+ mov r11, QWORD PTR [rdx+176]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+168], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+184]
+ mov r12, QWORD PTR [rdx+184]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+176], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+192]
+ mov r10, QWORD PTR [rdx+192]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+184], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+200]
+ mov r11, QWORD PTR [rdx+200]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+192], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+208]
+ mov r12, QWORD PTR [rdx+208]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+200], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+216]
+ mov r10, QWORD PTR [rdx+216]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+208], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+224]
+ mov r11, QWORD PTR [rdx+224]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+216], r10
+ adc r11, r12
+ mov r10, QWORD PTR [r8+232]
+ mov r12, QWORD PTR [rdx+232]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+224], r11
+ adc r12, r10
+ mov r11, QWORD PTR [r8+240]
+ mov r10, QWORD PTR [rdx+240]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+232], r12
+ adc r10, r11
+ mov r12, QWORD PTR [r8+248]
+ mov r11, QWORD PTR [rdx+248]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+240], r10
+ adc r11, r12
+ mov QWORD PTR [rcx+248], r11
+ adc rax, 0
+ pop r12
+ ret
+sp_4096_cond_add_avx2_32 ENDP
+_text ENDS
+ENDIF
+; /* Shift number left by n bit. (r = a << n)
+; *
+; * r Result of left shift by n.
+; * a Number to shift.
+; * n Amoutnt o shift.
+; */
+_text SEGMENT READONLY PARA
+sp_4096_lshift_64 PROC
+ push r12
+ push r13
+ mov r9, rcx
+ mov rcx, r8
+ mov r12, 0
+ mov r13, QWORD PTR [rdx+472]
+ mov rax, QWORD PTR [rdx+480]
+ mov r8, QWORD PTR [rdx+488]
+ mov r10, QWORD PTR [rdx+496]
+ mov r11, QWORD PTR [rdx+504]
+ shld r12, r11, cl
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+480], rax
+ mov QWORD PTR [r9+488], r8
+ mov QWORD PTR [r9+496], r10
+ mov QWORD PTR [r9+504], r11
+ mov QWORD PTR [r9+512], r12
+ mov r11, QWORD PTR [rdx+440]
+ mov rax, QWORD PTR [rdx+448]
+ mov r8, QWORD PTR [rdx+456]
+ mov r10, QWORD PTR [rdx+464]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+448], rax
+ mov QWORD PTR [r9+456], r8
+ mov QWORD PTR [r9+464], r10
+ mov QWORD PTR [r9+472], r13
+ mov r13, QWORD PTR [rdx+408]
+ mov rax, QWORD PTR [rdx+416]
+ mov r8, QWORD PTR [rdx+424]
+ mov r10, QWORD PTR [rdx+432]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+416], rax
+ mov QWORD PTR [r9+424], r8
+ mov QWORD PTR [r9+432], r10
+ mov QWORD PTR [r9+440], r11
+ mov r11, QWORD PTR [rdx+376]
+ mov rax, QWORD PTR [rdx+384]
+ mov r8, QWORD PTR [rdx+392]
+ mov r10, QWORD PTR [rdx+400]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+384], rax
+ mov QWORD PTR [r9+392], r8
+ mov QWORD PTR [r9+400], r10
+ mov QWORD PTR [r9+408], r13
+ mov r13, QWORD PTR [rdx+344]
+ mov rax, QWORD PTR [rdx+352]
+ mov r8, QWORD PTR [rdx+360]
+ mov r10, QWORD PTR [rdx+368]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+352], rax
+ mov QWORD PTR [r9+360], r8
+ mov QWORD PTR [r9+368], r10
+ mov QWORD PTR [r9+376], r11
+ mov r11, QWORD PTR [rdx+312]
+ mov rax, QWORD PTR [rdx+320]
+ mov r8, QWORD PTR [rdx+328]
+ mov r10, QWORD PTR [rdx+336]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+320], rax
+ mov QWORD PTR [r9+328], r8
+ mov QWORD PTR [r9+336], r10
+ mov QWORD PTR [r9+344], r13
+ mov r13, QWORD PTR [rdx+280]
+ mov rax, QWORD PTR [rdx+288]
+ mov r8, QWORD PTR [rdx+296]
+ mov r10, QWORD PTR [rdx+304]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+288], rax
+ mov QWORD PTR [r9+296], r8
+ mov QWORD PTR [r9+304], r10
+ mov QWORD PTR [r9+312], r11
+ mov r11, QWORD PTR [rdx+248]
+ mov rax, QWORD PTR [rdx+256]
+ mov r8, QWORD PTR [rdx+264]
+ mov r10, QWORD PTR [rdx+272]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+256], rax
+ mov QWORD PTR [r9+264], r8
+ mov QWORD PTR [r9+272], r10
+ mov QWORD PTR [r9+280], r13
+ mov r13, QWORD PTR [rdx+216]
+ mov rax, QWORD PTR [rdx+224]
+ mov r8, QWORD PTR [rdx+232]
+ mov r10, QWORD PTR [rdx+240]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+224], rax
+ mov QWORD PTR [r9+232], r8
+ mov QWORD PTR [r9+240], r10
+ mov QWORD PTR [r9+248], r11
+ mov r11, QWORD PTR [rdx+184]
+ mov rax, QWORD PTR [rdx+192]
+ mov r8, QWORD PTR [rdx+200]
+ mov r10, QWORD PTR [rdx+208]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+192], rax
+ mov QWORD PTR [r9+200], r8
+ mov QWORD PTR [r9+208], r10
+ mov QWORD PTR [r9+216], r13
+ mov r13, QWORD PTR [rdx+152]
+ mov rax, QWORD PTR [rdx+160]
+ mov r8, QWORD PTR [rdx+168]
+ mov r10, QWORD PTR [rdx+176]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+160], rax
+ mov QWORD PTR [r9+168], r8
+ mov QWORD PTR [r9+176], r10
+ mov QWORD PTR [r9+184], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov rax, QWORD PTR [rdx+128]
+ mov r8, QWORD PTR [rdx+136]
+ mov r10, QWORD PTR [rdx+144]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+128], rax
+ mov QWORD PTR [r9+136], r8
+ mov QWORD PTR [r9+144], r10
+ mov QWORD PTR [r9+152], r13
+ mov r13, QWORD PTR [rdx+88]
+ mov rax, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+96], rax
+ mov QWORD PTR [r9+104], r8
+ mov QWORD PTR [r9+112], r10
+ mov QWORD PTR [r9+120], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov rax, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r11, cl
+ mov QWORD PTR [r9+64], rax
+ mov QWORD PTR [r9+72], r8
+ mov QWORD PTR [r9+80], r10
+ mov QWORD PTR [r9+88], r13
+ mov r13, QWORD PTR [rdx+24]
+ mov rax, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ shld r11, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shld rax, r13, cl
+ mov QWORD PTR [r9+32], rax
+ mov QWORD PTR [r9+40], r8
+ mov QWORD PTR [r9+48], r10
+ mov QWORD PTR [r9+56], r11
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ shld r13, r10, cl
+ shld r10, r8, cl
+ shld r8, rax, cl
+ shl rax, cl
+ mov QWORD PTR [r9], rax
+ mov QWORD PTR [r9+8], r8
+ mov QWORD PTR [r9+16], r10
+ mov QWORD PTR [r9+24], r13
+ pop r13
+ pop r12
+ ret
+sp_4096_lshift_64 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFNDEF WOLFSSL_SP_NO_256
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mul_4 PROC
+ push r12
+ mov r9, rdx
+ sub rsp, 32
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ mov QWORD PTR [rsp], rax
+ mov r11, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+8], r11
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+16], r12
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+24], r10
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+8]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+32], r11
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+16]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+40], r12
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r10, QWORD PTR [rsp+16]
+ mov r11, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ add rsp, 32
+ pop r12
+ ret
+sp_256_mul_4 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_sqr_4 PROC
+ push r12
+ push r13
+ push r14
+ mov r8, rdx
+ sub rsp, 32
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ xor r11, r11
+ mov QWORD PTR [rsp], rax
+ mov r10, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+8], r10
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+16], r11
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+8]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+24], r9
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rcx+32], r10
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+16]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+40], r11
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ add r9, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+48], r9
+ mov QWORD PTR [rcx+56], r10
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r12, QWORD PTR [rsp+16]
+ mov r13, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ add rsp, 32
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_sqr_4 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_add_4 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx+24], r10
+ adc rax, 0
+ ret
+sp_256_add_4 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_sub_4 PROC
+ push r12
+ xor rax, rax
+ mov r9, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ sub r9, QWORD PTR [r8]
+ sbb r10, QWORD PTR [r8+8]
+ sbb r11, QWORD PTR [r8+16]
+ sbb r12, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx], r9
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ sbb rax, 0
+ pop r12
+ ret
+sp_256_sub_4 ENDP
+_text ENDS
+; /* Conditionally copy a into r using the mask m.
+; * m is -1 to copy and 0 when not.
+; *
+; * r A single precision number to copy over.
+; * a A single precision number to copy.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_256_cond_copy_4 PROC
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [rcx+16]
+ mov r11, QWORD PTR [rcx+24]
+ xor rax, QWORD PTR [rdx]
+ xor r9, QWORD PTR [rdx+8]
+ xor r10, QWORD PTR [rdx+16]
+ xor r11, QWORD PTR [rdx+24]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ xor QWORD PTR [rcx], rax
+ xor QWORD PTR [rcx+8], r9
+ xor QWORD PTR [rcx+16], r10
+ xor QWORD PTR [rcx+24], r11
+ ret
+sp_256_cond_copy_4 ENDP
+_text ENDS
+; /* Multiply two Montogmery form numbers mod the modulus (prime).
+; * (r = a * b mod m)
+; *
+; * r Result of multiplication.
+; * a First number to multiply in Montogmery form.
+; * b Second number to multiply in Montogmery form.
+; * m Modulus (prime).
+; * mp Montogmery mulitplier.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_mul_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov r10, rdx
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r10]
+ mov r11, rax
+ mov r12, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r10]
+ xor r13, r13
+ add r12, rax
+ adc r13, rdx
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r10+8]
+ xor r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r10]
+ add r13, rax
+ adc r14, rdx
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r10+8]
+ xor r15, r15
+ add r13, rax
+ adc r14, rdx
+ adc r15, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r10+16]
+ add r13, rax
+ adc r14, rdx
+ adc r15, 0
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r10]
+ xor rdi, rdi
+ add r14, rax
+ adc r15, rdx
+ adc rdi, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r10+8]
+ add r14, rax
+ adc r15, rdx
+ adc rdi, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r10+16]
+ add r14, rax
+ adc r15, rdx
+ adc rdi, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r10+24]
+ add r14, rax
+ adc r15, rdx
+ adc rdi, 0
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r10+8]
+ xor rsi, rsi
+ add r15, rax
+ adc rdi, rdx
+ adc rsi, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r10+16]
+ add r15, rax
+ adc rdi, rdx
+ adc rsi, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r10+24]
+ add r15, rax
+ adc rdi, rdx
+ adc rsi, 0
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r10+16]
+ xor rbx, rbx
+ add rdi, rax
+ adc rsi, rdx
+ adc rbx, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r10+24]
+ add rdi, rax
+ adc rsi, rdx
+ adc rbx, 0
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r10+24]
+ add rsi, rax
+ adc rbx, rdx
+ ; Start Reduction
+ ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192
+ ; - a[0] << 32 << 192
+ ; + (a[0] * 2) << 192
+ mov rax, r11
+ mov rdx, r14
+ add rdx, r11
+ mov r10, r12
+ add rdx, r11
+ mov r8, r13
+ ; a[0]-a[2] << 32
+ shl r11, 32
+ shld r13, r10, 32
+ shld r12, rax, 32
+ ; - a[0] << 32 << 192
+ sub rdx, r11
+ ; + a[0]-a[2] << 32 << 64
+ add r10, r11
+ adc r8, r12
+ adc rdx, r13
+ ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu
+ ; a += mu << 256
+ xor r11, r11
+ add r15, rax
+ adc rdi, r10
+ adc rsi, r8
+ adc rbx, rdx
+ sbb r11, 0
+ ; a += mu << 192
+ add r14, rax
+ adc r15, r10
+ adc rdi, r8
+ adc rsi, rdx
+ adc rbx, 0
+ sbb r11, 0
+ ; mu <<= 32
+ mov r9, rdx
+ shld rdx, r8, 32
+ shld r8, r10, 32
+ shld r10, rax, 32
+ shr r9, 32
+ shl rax, 32
+ ; a += (mu << 32) << 64
+ add r14, r8
+ adc r15, rdx
+ adc rdi, r9
+ adc rsi, 0
+ adc rbx, 0
+ sbb r11, 0
+ ; a -= (mu << 32) << 192
+ sub r14, rax
+ sbb r15, r10
+ sbb rdi, r8
+ sbb rsi, rdx
+ sbb rbx, r9
+ adc r11, 0
+ mov rax, 4294967295
+ mov r10, 18446744069414584321
+ ; mask m and sub from result if overflow
+ ; m[0] = -1 & mask = mask
+ and rax, r11
+ ; m[2] = 0 & mask = 0
+ and r10, r11
+ sub r15, r11
+ sbb rdi, rax
+ sbb rsi, 0
+ sbb rbx, r10
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ mov QWORD PTR [rcx+16], rsi
+ mov QWORD PTR [rcx+24], rbx
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mont_mul_4 ENDP
+_text ENDS
+; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
+; *
+; * r Result of squaring.
+; * a Number to square in Montogmery form.
+; * m Modulus (prime).
+; * mp Montogmery mulitplier.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_sqr_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov r8, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r8+8]
+ mov r11, rax
+ mov r12, rdx
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r8+16]
+ xor r13, r13
+ add r12, rax
+ adc r13, rdx
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r8+24]
+ xor r14, r14
+ add r13, rax
+ adc r14, rdx
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8+16]
+ xor r15, r15
+ add r13, rax
+ adc r14, rdx
+ adc r15, 0
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8+24]
+ add r14, rax
+ adc r15, rdx
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+24]
+ xor rdi, rdi
+ add r15, rax
+ adc rdi, rdx
+ ; Double
+ xor rsi, rsi
+ add r11, r11
+ adc r12, r12
+ adc r13, r13
+ adc r14, r14
+ adc r15, r15
+ adc rdi, rdi
+ adc rsi, 0
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ mov rax, rax
+ mov rdx, rdx
+ mov r10, rax
+ mov rbx, rdx
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ mov rax, rax
+ mov rdx, rdx
+ add r11, rbx
+ adc r12, rax
+ adc rdx, 0
+ mov rbx, rdx
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ mov rax, rax
+ mov rdx, rdx
+ add r13, rbx
+ adc r14, rax
+ adc rdx, 0
+ mov rbx, rdx
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ mov rax, rax
+ mov rdx, rdx
+ add r15, rbx
+ adc rdi, rax
+ adc rsi, rdx
+ ; Start Reduction
+ ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192
+ ; - a[0] << 32 << 192
+ ; + (a[0] * 2) << 192
+ mov rax, r10
+ mov rdx, r13
+ add rdx, r10
+ mov r8, r11
+ add rdx, r10
+ mov rbx, r12
+ ; a[0]-a[2] << 32
+ shl r10, 32
+ shld r12, r8, 32
+ shld r11, rax, 32
+ ; - a[0] << 32 << 192
+ sub rdx, r10
+ ; + a[0]-a[2] << 32 << 64
+ add r8, r10
+ adc rbx, r11
+ adc rdx, r12
+ ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu
+ ; a += mu << 256
+ xor r10, r10
+ add r14, rax
+ adc r15, r8
+ adc rdi, rbx
+ adc rsi, rdx
+ sbb r10, 0
+ ; a += mu << 192
+ add r13, rax
+ adc r14, r8
+ adc r15, rbx
+ adc rdi, rdx
+ adc rsi, 0
+ sbb r10, 0
+ ; mu <<= 32
+ mov r9, rdx
+ shld rdx, rbx, 32
+ shld rbx, r8, 32
+ shld r8, rax, 32
+ shr r9, 32
+ shl rax, 32
+ ; a += (mu << 32) << 64
+ add r13, rbx
+ adc r14, rdx
+ adc r15, r9
+ adc rdi, 0
+ adc rsi, 0
+ sbb r10, 0
+ ; a -= (mu << 32) << 192
+ sub r13, rax
+ sbb r14, r8
+ sbb r15, rbx
+ sbb rdi, rdx
+ sbb rsi, r9
+ adc r10, 0
+ mov rax, 4294967295
+ mov r8, 18446744069414584321
+ ; mask m and sub from result if overflow
+ ; m[0] = -1 & mask = mask
+ and rax, r10
+ ; m[2] = 0 & mask = 0
+ and r8, r10
+ sub r14, r10
+ sbb r15, rax
+ sbb rdi, 0
+ sbb rsi, r8
+ mov QWORD PTR [rcx], r14
+ mov QWORD PTR [rcx+8], r15
+ mov QWORD PTR [rcx+16], rdi
+ mov QWORD PTR [rcx+24], rsi
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mont_sqr_4 ENDP
+_text ENDS
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_256_cmp_4 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_256_cmp_4 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_256_cond_sub_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov rax, 0
+ mov r14, QWORD PTR [r8]
+ mov r15, QWORD PTR [r8+8]
+ mov rdi, QWORD PTR [r8+16]
+ mov rsi, QWORD PTR [r8+24]
+ and r14, r9
+ and r15, r9
+ and rdi, r9
+ and rsi, r9
+ mov r10, QWORD PTR [rdx]
+ mov r11, QWORD PTR [rdx+8]
+ mov r12, QWORD PTR [rdx+16]
+ mov r13, QWORD PTR [rdx+24]
+ sub r10, r14
+ sbb r11, r15
+ sbb r12, rdi
+ sbb r13, rsi
+ mov QWORD PTR [rcx], r10
+ mov QWORD PTR [rcx+8], r11
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ sbb rax, 0
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_cond_sub_4 ENDP
+_text ENDS
+; /* Reduce the number back to 256 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_reduce_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ ; i = 0
+ xor rdi, rdi
+ mov r10, 4
+ mov r15, rcx
+L_mont_loop_4:
+ ; mu = a[i] * mp
+ mov r14, QWORD PTR [r15]
+ imul r14, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, QWORD PTR [r9]
+ mov r12, QWORD PTR [r9+8]
+ mul r14
+ mov rsi, QWORD PTR [r15]
+ add rsi, rax
+ mov r11, rdx
+ mov QWORD PTR [r15], rsi
+ adc r11, 0
+ ; a[i+1] += m[1] * mu
+ mov rax, r12
+ mul r14
+ mov r12, QWORD PTR [r9+16]
+ mov rsi, QWORD PTR [r15+8]
+ add rax, r11
+ mov r13, rdx
+ adc r13, 0
+ add rsi, rax
+ mov QWORD PTR [r15+8], rsi
+ adc r13, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r12
+ mul r14
+ mov r12, QWORD PTR [r9+24]
+ mov rsi, QWORD PTR [r15+16]
+ add rax, r13
+ mov r11, rdx
+ adc r11, 0
+ add rsi, rax
+ mov QWORD PTR [r15+16], rsi
+ adc r11, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r12
+ mul r14
+ mov rsi, QWORD PTR [r15+24]
+ add rax, r11
+ adc rdx, rdi
+ mov rdi, 0
+ adc rdi, 0
+ add rsi, rax
+ mov QWORD PTR [r15+24], rsi
+ adc QWORD PTR [r15+32], rdx
+ adc rdi, 0
+ ; i += 1
+ add r15, 8
+ dec r10
+ jnz L_mont_loop_4
+ xor rax, rax
+ mov rdx, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [rcx+40]
+ mov rsi, QWORD PTR [rcx+48]
+ mov r11, QWORD PTR [rcx+56]
+ sub rax, rdi
+ mov r12, QWORD PTR [r9]
+ mov r13, QWORD PTR [r9+8]
+ mov r14, QWORD PTR [r9+16]
+ mov r15, QWORD PTR [r9+24]
+ and r12, rax
+ and r13, rax
+ and r14, rax
+ and r15, rax
+ sub rdx, r12
+ sbb r10, r13
+ sbb rsi, r14
+ sbb r11, r15
+ mov QWORD PTR [rcx], rdx
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], rsi
+ mov QWORD PTR [rcx+24], r11
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mont_reduce_4 ENDP
+_text ENDS
+; /* Add two Montgomery form numbers (r = a + b % m).
+; *
+; * r Result of addition.
+; * a First number to add in Montogmery form.
+; * b Second number to add in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_add_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ mov r12, 4294967295
+ mov r13, 18446744069414584321
+ add rax, QWORD PTR [r8]
+ adc r9, QWORD PTR [r8+8]
+ adc r10, QWORD PTR [r8+16]
+ mov rdx, 0
+ adc r11, QWORD PTR [r8+24]
+ sbb rdx, 0
+ and r12, rdx
+ and r13, rdx
+ sub rax, rdx
+ sbb r9, r12
+ mov QWORD PTR [rcx], rax
+ sbb r10, 0
+ mov QWORD PTR [rcx+8], r9
+ sbb r11, r13
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ pop r13
+ pop r12
+ ret
+sp_256_mont_add_4 ENDP
+_text ENDS
+; /* Double a Montgomery form number (r = a + a % m).
+; *
+; * r Result of doubling.
+; * a Number to double in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_dbl_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov r11, 4294967295
+ mov r12, 18446744069414584321
+ add rax, rax
+ adc r8, r8
+ adc r9, r9
+ mov r13, 0
+ adc r10, r10
+ sbb r13, 0
+ and r11, r13
+ and r12, r13
+ sub rax, r13
+ sbb r8, r11
+ mov QWORD PTR [rcx], rax
+ sbb r9, 0
+ mov QWORD PTR [rcx+8], r8
+ sbb r10, r12
+ mov QWORD PTR [rcx+16], r9
+ mov QWORD PTR [rcx+24], r10
+ pop r13
+ pop r12
+ ret
+sp_256_mont_dbl_4 ENDP
+_text ENDS
+; /* Triple a Montgomery form number (r = a + a + a % m).
+; *
+; * r Result of Tripling.
+; * a Number to triple in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_tpl_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov r11, 4294967295
+ mov r12, 18446744069414584321
+ add rax, rax
+ adc r8, r8
+ adc r9, r9
+ mov r13, 0
+ adc r10, r10
+ sbb r13, 0
+ and r11, r13
+ and r12, r13
+ sub rax, r13
+ sbb r8, r11
+ sbb r9, 0
+ sbb r10, r12
+ mov r11, 4294967295
+ mov r12, 18446744069414584321
+ add rax, QWORD PTR [rdx]
+ adc r8, QWORD PTR [rdx+8]
+ adc r9, QWORD PTR [rdx+16]
+ mov r13, 0
+ adc r10, QWORD PTR [rdx+24]
+ sbb r13, 0
+ and r11, r13
+ and r12, r13
+ sub rax, r13
+ sbb r8, r11
+ mov QWORD PTR [rcx], rax
+ sbb r9, 0
+ mov QWORD PTR [rcx+8], r8
+ sbb r10, r12
+ mov QWORD PTR [rcx+16], r9
+ mov QWORD PTR [rcx+24], r10
+ pop r13
+ pop r12
+ ret
+sp_256_mont_tpl_4 ENDP
+_text ENDS
+; /* Subtract two Montgomery form numbers (r = a - b % m).
+; *
+; * r Result of subtration.
+; * a Number to subtract from in Montogmery form.
+; * b Number to subtract with in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_sub_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ mov r12, 4294967295
+ mov r13, 18446744069414584321
+ sub rax, QWORD PTR [r8]
+ sbb r9, QWORD PTR [r8+8]
+ sbb r10, QWORD PTR [r8+16]
+ mov rdx, 0
+ sbb r11, QWORD PTR [r8+24]
+ sbb rdx, 0
+ and r12, rdx
+ and r13, rdx
+ add rax, rdx
+ adc r9, r12
+ mov QWORD PTR [rcx], rax
+ adc r10, 0
+ mov QWORD PTR [rcx+8], r9
+ adc r11, r13
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ pop r13
+ pop r12
+ ret
+sp_256_mont_sub_4 ENDP
+_text ENDS
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_div2_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov r11, 4294967295
+ mov r12, 18446744069414584321
+ mov r13, rax
+ and r13, 1
+ neg r13
+ and r11, r13
+ and r12, r13
+ add rax, r13
+ adc r8, r11
+ adc r9, 0
+ adc r10, r12
+ mov r13, 0
+ adc r13, 0
+ shrd rax, r8, 1
+ shrd r8, r9, 1
+ shrd r9, r10, 1
+ shrd r10, r13, 1
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r8
+ mov QWORD PTR [rcx+16], r9
+ mov QWORD PTR [rcx+24], r10
+ pop r13
+ pop r12
+ ret
+sp_256_div2_4 ENDP
+_text ENDS
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible point that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of point to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_point_33_4 PROC
+ mov rax, 1
+ movd xmm13, r8d
+ add rdx, 200
+ movd xmm15, eax
+ mov rax, 32
+ pshufd xmm15, xmm15, 0
+ pshufd xmm13, xmm13, 0
+ pxor xmm14, xmm14
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ pxor xmm4, xmm4
+ pxor xmm5, xmm5
+ movdqa xmm14, xmm15
+L_256_get_point_33_4_start:
+ movdqa xmm12, xmm14
+ paddd xmm14, xmm15
+ pcmpeqd xmm12, xmm13
+ movdqu xmm6, [rdx]
+ movdqu xmm7, [rdx+16]
+ movdqu xmm8, [rdx+64]
+ movdqu xmm9, [rdx+80]
+ movdqu xmm10, [rdx+128]
+ movdqu xmm11, [rdx+144]
+ add rdx, 200
+ pand xmm6, xmm12
+ pand xmm7, xmm12
+ pand xmm8, xmm12
+ pand xmm9, xmm12
+ pand xmm10, xmm12
+ pand xmm11, xmm12
+ por xmm0, xmm6
+ por xmm1, xmm7
+ por xmm2, xmm8
+ por xmm3, xmm9
+ por xmm4, xmm10
+ por xmm5, xmm11
+ dec rax
+ jnz L_256_get_point_33_4_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+64], xmm2
+ movdqu [rcx+80], xmm3
+ movdqu [rcx+128], xmm4
+ movdqu [rcx+144], xmm5
+ ret
+sp_256_get_point_33_4 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible point that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of point to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_point_33_avx2_4 PROC
+ mov rax, 1
+ movd xmm7, r8d
+ add rdx, 200
+ movd xmm9, eax
+ mov rax, 32
+ vpxor ymm8, ymm8, ymm8
+ vpermd ymm7, ymm8, ymm7
+ vpermd ymm9, ymm8, ymm9
+ vpxor ymm0, ymm0, ymm0
+ vpxor ymm1, ymm1, ymm1
+ vpxor ymm2, ymm2, ymm2
+ vmovdqa ymm8, ymm9
+L_256_get_point_33_avx2_4_start:
+ vpcmpeqd ymm6, ymm8, ymm7
+ vpaddd ymm8, ymm8, ymm9
+ vmovupd ymm3, [rdx]
+ vmovupd ymm4, [rdx+64]
+ vmovupd ymm5, [rdx+128]
+ add rdx, 200
+ vpand ymm3, ymm3, ymm6
+ vpand ymm4, ymm4, ymm6
+ vpand ymm5, ymm5, ymm6
+ vpor ymm0, ymm0, ymm3
+ vpor ymm1, ymm1, ymm4
+ vpor ymm2, ymm2, ymm5
+ dec rax
+ jnz L_256_get_point_33_avx2_4_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovupd YMMWORD PTR [rcx+64], ymm1
+ vmovupd YMMWORD PTR [rcx+128], ymm2
+ ret
+sp_256_get_point_33_avx2_4 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply two Montogmery form numbers mod the modulus (prime).
+; * (r = a * b mod m)
+; *
+; * r Result of multiplication.
+; * a First number to multiply in Montogmery form.
+; * b Second number to multiply in Montogmery form.
+; * m Modulus (prime).
+; * mp Montogmery mulitplier.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_mul_avx2_4 PROC
+ push rbx
+ push r12
+ push r13
+ push r14
+ push r15
+ push rbp
+ push rdi
+ push rsi
+ mov rbp, r8
+ mov rdi, rdx
+ ; A[0] * B[0]
+ mov rdx, QWORD PTR [rbp]
+ mulx r9, r8, QWORD PTR [rdi]
+ ; A[2] * B[0]
+ mulx r11, r10, QWORD PTR [rdi+16]
+ ; A[1] * B[0]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ xor r15, r15
+ adcx r9, rax
+ ; A[1] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ mulx r13, r12, QWORD PTR [rdi+8]
+ adcx r10, rsi
+ ; A[0] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r9, rax
+ ; A[2] * B[1]
+ mulx r14, rax, QWORD PTR [rdi+16]
+ adox r10, rsi
+ adcx r11, rax
+ ; A[1] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ adcx r12, r14
+ adox r11, rax
+ adcx r13, r15
+ adox r12, rsi
+ ; A[0] * B[2]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r13, r15
+ xor r14, r14
+ adcx r10, rax
+ ; A[1] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rax, rdx, QWORD PTR [rdi+8]
+ adcx r11, rsi
+ adox r10, rdx
+ ; A[3] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ adox r11, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adcx r12, rax
+ ; A[2] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rax, rdx, QWORD PTR [rdi+16]
+ adcx r13, rsi
+ adox r12, rdx
+ ; A[3] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adox r13, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adox r14, r15
+ adcx r14, rax
+ ; A[0] * B[3]
+ mulx rax, rdx, QWORD PTR [rdi]
+ adcx r15, rsi
+ xor rsi, rsi
+ adcx r11, rdx
+ ; A[3] * B[0]
+ mov rdx, QWORD PTR [rdi+24]
+ adcx r12, rax
+ mulx rax, rbx, QWORD PTR [rbp]
+ adox r11, rbx
+ adox r12, rax
+ ; A[3] * B[2]
+ mulx rax, rdx, QWORD PTR [rbp+16]
+ adcx r13, rdx
+ ; A[2] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adcx r14, rax
+ mulx rdx, rax, QWORD PTR [rdi+16]
+ adcx r15, rsi
+ adox r13, rax
+ adox r14, rdx
+ adox r15, rsi
+ ; Start Reduction
+ ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192
+ ; - a[0] << 32 << 192
+ ; + (a[0] * 2) << 192
+ mov rax, r8
+ mov rdx, r11
+ add rdx, r8
+ mov rdi, r9
+ add rdx, r8
+ mov rbp, r10
+ ; a[0]-a[2] << 32
+ shl r8, 32
+ shld r10, rdi, 32
+ shld r9, rax, 32
+ ; - a[0] << 32 << 192
+ sub rdx, r8
+ ; + a[0]-a[2] << 32 << 64
+ add rdi, r8
+ adc rbp, r9
+ adc rdx, r10
+ ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu
+ ; a += mu << 256
+ xor r8, r8
+ add r12, rax
+ adc r13, rdi
+ adc r14, rbp
+ adc r15, rdx
+ sbb r8, 0
+ ; a += mu << 192
+ add r11, rax
+ adc r12, rdi
+ adc r13, rbp
+ adc r14, rdx
+ adc r15, 0
+ sbb r8, 0
+ ; mu <<= 32
+ mov rsi, rdx
+ shld rdx, rbp, 32
+ shld rbp, rdi, 32
+ shld rdi, rax, 32
+ shr rsi, 32
+ shl rax, 32
+ ; a += (mu << 32) << 64
+ add r11, rbp
+ adc r12, rdx
+ adc r13, rsi
+ adc r14, 0
+ adc r15, 0
+ sbb r8, 0
+ ; a -= (mu << 32) << 192
+ sub r11, rax
+ sbb r12, rdi
+ sbb r13, rbp
+ sbb r14, rdx
+ sbb r15, rsi
+ adc r8, 0
+ mov rax, 4294967295
+ mov rdi, 18446744069414584321
+ ; mask m and sub from result if overflow
+ ; m[0] = -1 & mask = mask
+ and rax, r8
+ ; m[2] = 0 & mask = 0
+ and rdi, r8
+ sub r12, r8
+ sbb r13, rax
+ sbb r14, 0
+ sbb r15, rdi
+ mov QWORD PTR [rcx], r12
+ mov QWORD PTR [rcx+8], r13
+ mov QWORD PTR [rcx+16], r14
+ mov QWORD PTR [rcx+24], r15
+ pop rsi
+ pop rdi
+ pop rbp
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbx
+ ret
+sp_256_mont_mul_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
+; *
+; * r Result of squaring.
+; * a Number to square in Montogmery form.
+; * m Modulus (prime).
+; * mp Montogmery mulitplier.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_sqr_avx2_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov rax, rdx
+ ; A[0] * A[1]
+ mov rdx, QWORD PTR [rax]
+ mov r15, QWORD PTR [rax+16]
+ mulx r10, r9, QWORD PTR [rax+8]
+ ; A[0] * A[3]
+ mulx r12, r11, QWORD PTR [rax+24]
+ ; A[2] * A[1]
+ mov rdx, r15
+ mulx rbx, rsi, QWORD PTR [rax+8]
+ ; A[2] * A[3]
+ mulx r14, r13, QWORD PTR [rax+24]
+ xor r15, r15
+ adox r11, rsi
+ adox r12, rbx
+ ; A[2] * A[0]
+ mulx rbx, rsi, QWORD PTR [rax]
+ ; A[1] * A[3]
+ mov rdx, QWORD PTR [rax+8]
+ adox r13, r15
+ mulx r8, rdi, QWORD PTR [rax+24]
+ adcx r10, rsi
+ adox r14, r15
+ adcx r11, rbx
+ adcx r12, rdi
+ adcx r13, r8
+ adcx r14, r15
+ ; Double with Carry Flag
+ xor r15, r15
+ ; A[0] * A[0]
+ mov rdx, QWORD PTR [rax]
+ mulx rdi, r8, rdx
+ adcx r9, r9
+ adcx r10, r10
+ adox r9, rdi
+ ; A[1] * A[1]
+ mov rdx, QWORD PTR [rax+8]
+ mulx rbx, rsi, rdx
+ adcx r11, r11
+ adox r10, rsi
+ ; A[2] * A[2]
+ mov rdx, QWORD PTR [rax+16]
+ mulx rsi, rdi, rdx
+ adcx r12, r12
+ adox r11, rbx
+ adcx r13, r13
+ adox r12, rdi
+ adcx r14, r14
+ ; A[3] * A[3]
+ mov rdx, QWORD PTR [rax+24]
+ mulx rbx, rdi, rdx
+ adox r13, rsi
+ adcx r15, r15
+ adox r14, rdi
+ adox r15, rbx
+ ; Start Reduction
+ ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192
+ ; - a[0] << 32 << 192
+ ; + (a[0] * 2) << 192
+ mov rdi, r8
+ mov rdx, r11
+ add rdx, r8
+ mov rax, r9
+ add rdx, r8
+ mov rsi, r10
+ ; a[0]-a[2] << 32
+ shl r8, 32
+ shld r10, rax, 32
+ shld r9, rdi, 32
+ ; - a[0] << 32 << 192
+ sub rdx, r8
+ ; + a[0]-a[2] << 32 << 64
+ add rax, r8
+ adc rsi, r9
+ adc rdx, r10
+ ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu
+ ; a += mu << 256
+ xor r8, r8
+ add r12, rdi
+ adc r13, rax
+ adc r14, rsi
+ adc r15, rdx
+ sbb r8, 0
+ ; a += mu << 192
+ add r11, rdi
+ adc r12, rax
+ adc r13, rsi
+ adc r14, rdx
+ adc r15, 0
+ sbb r8, 0
+ ; mu <<= 32
+ mov rbx, rdx
+ shld rdx, rsi, 32
+ shld rsi, rax, 32
+ shld rax, rdi, 32
+ shr rbx, 32
+ shl rdi, 32
+ ; a += (mu << 32) << 64
+ add r11, rsi
+ adc r12, rdx
+ adc r13, rbx
+ adc r14, 0
+ adc r15, 0
+ sbb r8, 0
+ ; a -= (mu << 32) << 192
+ sub r11, rdi
+ sbb r12, rax
+ sbb r13, rsi
+ sbb r14, rdx
+ sbb r15, rbx
+ adc r8, 0
+ mov rdi, 4294967295
+ mov rax, 18446744069414584321
+ ; mask m and sub from result if overflow
+ ; m[0] = -1 & mask = mask
+ and rdi, r8
+ ; m[2] = 0 & mask = 0
+ and rax, r8
+ sub r12, r8
+ sbb r13, rdi
+ sbb r14, 0
+ sbb r15, rax
+ mov QWORD PTR [rcx], r12
+ mov QWORD PTR [rcx+8], r13
+ mov QWORD PTR [rcx+16], r14
+ mov QWORD PTR [rcx+24], r15
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mont_sqr_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_256_cond_sub_avx2_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov rax, 0
+ mov r14, QWORD PTR [r8]
+ mov r15, QWORD PTR [r8+8]
+ mov rdi, QWORD PTR [r8+16]
+ mov rsi, QWORD PTR [r8+24]
+ and r14, r9
+ and r15, r9
+ and rdi, r9
+ and rsi, r9
+ mov r10, QWORD PTR [rdx]
+ mov r11, QWORD PTR [rdx+8]
+ mov r12, QWORD PTR [rdx+16]
+ mov r13, QWORD PTR [rdx+24]
+ sub r10, r14
+ sbb r11, r15
+ sbb r12, rdi
+ sbb r13, rsi
+ mov QWORD PTR [rcx], r10
+ mov QWORD PTR [rcx+8], r11
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ sbb rax, 0
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_cond_sub_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 256 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_reduce_avx2_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov rax, rcx
+ mov r10, rdx
+ mov r11, r8
+ mov r14, QWORD PTR [rax]
+ mov r15, QWORD PTR [rax+8]
+ mov rdi, QWORD PTR [rax+16]
+ mov rsi, QWORD PTR [rax+24]
+ xor r13, r13
+ xor r12, r12
+ ; a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp)
+ mov rbx, QWORD PTR [rax+32]
+ ; mu = a[0] * mp
+ mov rdx, r14
+ mulx rcx, rdx, r11
+ ; a[0] += m[0] * mu
+ mulx r9, r8, QWORD PTR [r10]
+ adcx r14, r8
+ ; a[1] += m[1] * mu
+ mulx rcx, r8, QWORD PTR [r10+8]
+ adox r15, r9
+ adcx r15, r8
+ ; a[2] += m[2] * mu
+ mulx r9, r8, QWORD PTR [r10+16]
+ adox rdi, rcx
+ adcx rdi, r8
+ ; a[3] += m[3] * mu
+ mulx rcx, r8, QWORD PTR [r10+24]
+ adox rsi, r9
+ adcx rsi, r8
+ ; a[4] += carry
+ adox rbx, rcx
+ adcx rbx, r12
+ ; carry
+ adox r13, r12
+ adcx r13, r12
+ ; a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp)
+ mov r14, QWORD PTR [rax+40]
+ ; mu = a[1] * mp
+ mov rdx, r15
+ mulx rcx, rdx, r11
+ ; a[1] += m[0] * mu
+ mulx r9, r8, QWORD PTR [r10]
+ adcx r15, r8
+ ; a[2] += m[1] * mu
+ mulx rcx, r8, QWORD PTR [r10+8]
+ adox rdi, r9
+ adcx rdi, r8
+ ; a[3] += m[2] * mu
+ mulx r9, r8, QWORD PTR [r10+16]
+ adox rsi, rcx
+ adcx rsi, r8
+ ; a[4] += m[3] * mu
+ mulx rcx, r8, QWORD PTR [r10+24]
+ adox rbx, r9
+ adcx rbx, r8
+ ; a[5] += carry
+ adox r14, rcx
+ adcx r14, r13
+ mov r13, r12
+ ; carry
+ adox r13, r12
+ adcx r13, r12
+ ; a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp)
+ mov r15, QWORD PTR [rax+48]
+ ; mu = a[2] * mp
+ mov rdx, rdi
+ mulx rcx, rdx, r11
+ ; a[2] += m[0] * mu
+ mulx r9, r8, QWORD PTR [r10]
+ adcx rdi, r8
+ ; a[3] += m[1] * mu
+ mulx rcx, r8, QWORD PTR [r10+8]
+ adox rsi, r9
+ adcx rsi, r8
+ ; a[4] += m[2] * mu
+ mulx r9, r8, QWORD PTR [r10+16]
+ adox rbx, rcx
+ adcx rbx, r8
+ ; a[5] += m[3] * mu
+ mulx rcx, r8, QWORD PTR [r10+24]
+ adox r14, r9
+ adcx r14, r8
+ ; a[6] += carry
+ adox r15, rcx
+ adcx r15, r13
+ mov r13, r12
+ ; carry
+ adox r13, r12
+ adcx r13, r12
+ ; a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp)
+ mov rdi, QWORD PTR [rax+56]
+ ; mu = a[3] * mp
+ mov rdx, rsi
+ mulx rcx, rdx, r11
+ ; a[3] += m[0] * mu
+ mulx r9, r8, QWORD PTR [r10]
+ adcx rsi, r8
+ ; a[4] += m[1] * mu
+ mulx rcx, r8, QWORD PTR [r10+8]
+ adox rbx, r9
+ adcx rbx, r8
+ ; a[5] += m[2] * mu
+ mulx r9, r8, QWORD PTR [r10+16]
+ adox r14, rcx
+ adcx r14, r8
+ ; a[6] += m[3] * mu
+ mulx rcx, r8, QWORD PTR [r10+24]
+ adox r15, r9
+ adcx r15, r8
+ ; a[7] += carry
+ adox rdi, rcx
+ adcx rdi, r13
+ mov r13, r12
+ ; carry
+ adox r13, r12
+ adcx r13, r12
+ ; Subtract mod if carry
+ neg r13
+ mov r8, 17562291160714782033
+ mov r9, 13611842547513532036
+ mov rdx, 18446744069414584320
+ and r8, r13
+ and r9, r13
+ and rdx, r13
+ sub rbx, r8
+ sbb r14, r9
+ sbb r15, r13
+ sbb rdi, rdx
+ mov QWORD PTR [rax], rbx
+ mov QWORD PTR [rax+8], r14
+ mov QWORD PTR [rax+16], r15
+ mov QWORD PTR [rax+24], rdi
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mont_reduce_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_256_div2_avx2_4 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov r11, 4294967295
+ mov r12, 18446744069414584321
+ mov r13, rax
+ and r13, 1
+ neg r13
+ and r11, r13
+ and r12, r13
+ add rax, r13
+ adc r8, r11
+ adc r9, 0
+ adc r10, r12
+ mov r13, 0
+ adc r13, 0
+ shrd rax, r8, 1
+ shrd r8, r9, 1
+ shrd r9, r10, 1
+ shrd r10, r13, 1
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r8
+ mov QWORD PTR [rcx+16], r9
+ mov QWORD PTR [rcx+24], r10
+ pop r13
+ pop r12
+ ret
+sp_256_div2_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_entry_64_4 PROC
+ mov rax, 1
+ movd xmm9, r8d
+ add rdx, 64
+ movd xmm11, eax
+ mov rax, 63
+ pshufd xmm11, xmm11, 0
+ pshufd xmm9, xmm9, 0
+ pxor xmm10, xmm10
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ movdqa xmm10, xmm11
+L_256_get_entry_64_4_start:
+ movdqa xmm8, xmm10
+ paddd xmm10, xmm11
+ pcmpeqd xmm8, xmm9
+ movdqa xmm4, [rdx]
+ movdqa xmm5, [rdx+16]
+ movdqa xmm6, [rdx+32]
+ movdqa xmm7, [rdx+48]
+ add rdx, 64
+ pand xmm4, xmm8
+ pand xmm5, xmm8
+ pand xmm6, xmm8
+ pand xmm7, xmm8
+ por xmm0, xmm4
+ por xmm1, xmm5
+ por xmm2, xmm6
+ por xmm3, xmm7
+ dec rax
+ jnz L_256_get_entry_64_4_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+64], xmm2
+ movdqu [rcx+80], xmm3
+ ret
+sp_256_get_entry_64_4 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_entry_64_avx2_4 PROC
+ mov rax, 1
+ movd xmm5, r8d
+ add rdx, 64
+ movd xmm7, eax
+ mov rax, 64
+ vpxor ymm6, ymm6, ymm6
+ vpermd ymm5, ymm6, ymm5
+ vpermd ymm7, ymm6, ymm7
+ vpxor ymm0, ymm0, ymm0
+ vpxor ymm1, ymm1, ymm1
+ vmovdqa ymm6, ymm7
+L_256_get_entry_64_avx2_4_start:
+ vpcmpeqd ymm4, ymm6, ymm5
+ vpaddd ymm6, ymm6, ymm7
+ vmovupd ymm2, [rdx]
+ vmovupd ymm3, [rdx+32]
+ add rdx, 64
+ vpand ymm2, ymm2, ymm4
+ vpand ymm3, ymm3, ymm4
+ vpor ymm0, ymm0, ymm2
+ vpor ymm1, ymm1, ymm3
+ dec rax
+ jnz L_256_get_entry_64_avx2_4_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovupd YMMWORD PTR [rcx+64], ymm1
+ ret
+sp_256_get_entry_64_avx2_4 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_entry_65_4 PROC
+ mov rax, 1
+ movd xmm9, r8d
+ add rdx, 64
+ movd xmm11, eax
+ mov rax, 64
+ pshufd xmm11, xmm11, 0
+ pshufd xmm9, xmm9, 0
+ pxor xmm10, xmm10
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ movdqa xmm10, xmm11
+L_256_get_entry_65_4_start:
+ movdqa xmm8, xmm10
+ paddd xmm10, xmm11
+ pcmpeqd xmm8, xmm9
+ movdqa xmm4, [rdx]
+ movdqa xmm5, [rdx+16]
+ movdqa xmm6, [rdx+32]
+ movdqa xmm7, [rdx+48]
+ add rdx, 64
+ pand xmm4, xmm8
+ pand xmm5, xmm8
+ pand xmm6, xmm8
+ pand xmm7, xmm8
+ por xmm0, xmm4
+ por xmm1, xmm5
+ por xmm2, xmm6
+ por xmm3, xmm7
+ dec rax
+ jnz L_256_get_entry_65_4_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+64], xmm2
+ movdqu [rcx+80], xmm3
+ ret
+sp_256_get_entry_65_4 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_256_get_entry_65_avx2_4 PROC
+ mov rax, 1
+ movd xmm5, r8d
+ add rdx, 64
+ movd xmm7, eax
+ mov rax, 65
+ vpxor ymm6, ymm6, ymm6
+ vpermd ymm5, ymm6, ymm5
+ vpermd ymm7, ymm6, ymm7
+ vpxor ymm0, ymm0, ymm0
+ vpxor ymm1, ymm1, ymm1
+ vmovdqa ymm6, ymm7
+L_256_get_entry_65_avx2_4_start:
+ vpcmpeqd ymm4, ymm6, ymm5
+ vpaddd ymm6, ymm6, ymm7
+ vmovupd ymm2, [rdx]
+ vmovupd ymm3, [rdx+32]
+ add rdx, 64
+ vpand ymm2, ymm2, ymm4
+ vpand ymm3, ymm3, ymm4
+ vpor ymm0, ymm0, ymm2
+ vpor ymm1, ymm1, ymm3
+ dec rax
+ jnz L_256_get_entry_65_avx2_4_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovupd YMMWORD PTR [rcx+64], ymm1
+ ret
+sp_256_get_entry_65_avx2_4 ENDP
+_text ENDS
+ENDIF
+ENDIF
+; /* Add 1 to a. (a = a + 1)
+; *
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_add_one_4 PROC
+ add QWORD PTR [rcx], 1
+ adc QWORD PTR [rcx+8], 0
+ adc QWORD PTR [rcx+16], 0
+ adc QWORD PTR [rcx+24], 0
+ ret
+sp_256_add_one_4 ENDP
+_text ENDS
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_256_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 32
+ xor r13, r13
+ jmp L_256_from_bin_bswap_64_end
+L_256_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_256_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_256_from_bin_bswap_64_start
+ jmp L_256_from_bin_bswap_8_end
+L_256_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_256_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_256_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_256_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_256_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_256_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_256_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_256_from_bin_bswap_zero_end
+L_256_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_256_from_bin_bswap_zero_start
+L_256_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_256_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_256_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 32
+ xor r13, r13
+ jmp L_256_from_bin_movbe_64_end
+L_256_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_256_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_256_from_bin_movbe_64_start
+ jmp L_256_from_bin_movbe_8_end
+L_256_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_256_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_256_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_256_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_256_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_256_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_256_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_256_from_bin_movbe_zero_end
+L_256_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_256_from_bin_movbe_zero_start
+L_256_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_256_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 32
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_256_to_bin_bswap PROC
+ mov rax, QWORD PTR [rcx+24]
+ mov r8, QWORD PTR [rcx+16]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ mov rax, QWORD PTR [rcx+8]
+ mov r8, QWORD PTR [rcx]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ ret
+sp_256_to_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 32
+; * Uses the movbe instruction which is optional.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_256_to_bin_movbe PROC
+ movbe rax, QWORD PTR [rcx+24]
+ movbe r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ movbe rax, QWORD PTR [rcx+8]
+ movbe r8, QWORD PTR [rcx]
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ ret
+sp_256_to_bin_movbe ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r Result of multiplication.
+; * a First number to multiply.
+; * b Second number to multiply.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mul_avx2_4 PROC
+ push rbx
+ push r12
+ push r13
+ push r14
+ push r15
+ push rbp
+ push rdi
+ push rsi
+ mov rbp, r8
+ mov rdi, rdx
+ ; A[0] * B[0]
+ mov rdx, QWORD PTR [rbp]
+ mulx r9, r8, QWORD PTR [rdi]
+ ; A[2] * B[0]
+ mulx r11, r10, QWORD PTR [rdi+16]
+ ; A[1] * B[0]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ xor r15, r15
+ adcx r9, rax
+ ; A[1] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ mulx r13, r12, QWORD PTR [rdi+8]
+ adcx r10, rsi
+ ; A[0] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r9, rax
+ ; A[2] * B[1]
+ mulx r14, rax, QWORD PTR [rdi+16]
+ adox r10, rsi
+ adcx r11, rax
+ ; A[1] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ adcx r12, r14
+ adox r11, rax
+ adcx r13, r15
+ adox r12, rsi
+ ; A[0] * B[2]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r13, r15
+ xor r14, r14
+ adcx r10, rax
+ ; A[1] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rax, rdx, QWORD PTR [rdi+8]
+ adcx r11, rsi
+ adox r10, rdx
+ ; A[3] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ adox r11, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adcx r12, rax
+ ; A[2] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rax, rdx, QWORD PTR [rdi+16]
+ adcx r13, rsi
+ adox r12, rdx
+ ; A[3] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adox r13, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adox r14, r15
+ adcx r14, rax
+ ; A[0] * B[3]
+ mulx rax, rdx, QWORD PTR [rdi]
+ adcx r15, rsi
+ xor rsi, rsi
+ adcx r11, rdx
+ ; A[3] * B[0]
+ mov rdx, QWORD PTR [rdi+24]
+ adcx r12, rax
+ mulx rax, rbx, QWORD PTR [rbp]
+ adox r11, rbx
+ adox r12, rax
+ ; A[3] * B[2]
+ mulx rax, rdx, QWORD PTR [rbp+16]
+ adcx r13, rdx
+ ; A[2] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adcx r14, rax
+ mulx rdx, rax, QWORD PTR [rdi+16]
+ adcx r15, rsi
+ adox r13, rax
+ adox r14, rdx
+ adox r15, rsi
+ mov QWORD PTR [rcx], r8
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov QWORD PTR [rcx+32], r12
+ mov QWORD PTR [rcx+40], r13
+ mov QWORD PTR [rcx+48], r14
+ mov QWORD PTR [rcx+56], r15
+ pop rsi
+ pop rdi
+ pop rbp
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbx
+ ret
+sp_256_mul_avx2_4 ENDP
+_text ENDS
+ENDIF
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_256_sub_in_place_4 PROC
+ xor rax, rax
+ mov r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ sub QWORD PTR [rcx], r8
+ sbb QWORD PTR [rcx+8], r9
+ sbb QWORD PTR [rcx+16], r10
+ sbb QWORD PTR [rcx+24], r11
+ sbb rax, 0
+ ret
+sp_256_sub_in_place_4 ENDP
+_text ENDS
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mul_d_4 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+24], r10
+ mov QWORD PTR [rcx+32], r11
+ pop r12
+ ret
+sp_256_mul_d_4 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mul_d_avx2_4 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+24], r12
+ mov QWORD PTR [rcx+32], r11
+ pop r13
+ pop r12
+ ret
+sp_256_mul_d_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_256_word_asm_4 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_256_word_asm_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply two Montogmery form numbers mod the modulus (prime).
+; * (r = a * b mod m)
+; *
+; * r Result of multiplication.
+; * a First number to multiply in Montogmery form.
+; * b Second number to multiply in Montogmery form.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_mul_order_avx2_4 PROC
+ push rbx
+ push r12
+ push r13
+ push r14
+ push r15
+ push rbp
+ push rdi
+ push rsi
+ mov rbp, r8
+ mov rdi, rdx
+ ; A[0] * B[0]
+ mov rdx, QWORD PTR [rbp]
+ mulx r9, r8, QWORD PTR [rdi]
+ ; A[2] * B[0]
+ mulx r11, r10, QWORD PTR [rdi+16]
+ ; A[1] * B[0]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ xor r15, r15
+ adcx r9, rax
+ ; A[1] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ mulx r13, r12, QWORD PTR [rdi+8]
+ adcx r10, rsi
+ ; A[0] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r9, rax
+ ; A[2] * B[1]
+ mulx r14, rax, QWORD PTR [rdi+16]
+ adox r10, rsi
+ adcx r11, rax
+ ; A[1] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rsi, rax, QWORD PTR [rdi+8]
+ adcx r12, r14
+ adox r11, rax
+ adcx r13, r15
+ adox r12, rsi
+ ; A[0] * B[2]
+ mulx rsi, rax, QWORD PTR [rdi]
+ adox r13, r15
+ xor r14, r14
+ adcx r10, rax
+ ; A[1] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ mulx rax, rdx, QWORD PTR [rdi+8]
+ adcx r11, rsi
+ adox r10, rdx
+ ; A[3] * B[1]
+ mov rdx, QWORD PTR [rbp+8]
+ adox r11, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adcx r12, rax
+ ; A[2] * B[2]
+ mov rdx, QWORD PTR [rbp+16]
+ mulx rax, rdx, QWORD PTR [rdi+16]
+ adcx r13, rsi
+ adox r12, rdx
+ ; A[3] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adox r13, rax
+ mulx rsi, rax, QWORD PTR [rdi+24]
+ adox r14, r15
+ adcx r14, rax
+ ; A[0] * B[3]
+ mulx rax, rdx, QWORD PTR [rdi]
+ adcx r15, rsi
+ xor rsi, rsi
+ adcx r11, rdx
+ ; A[3] * B[0]
+ mov rdx, QWORD PTR [rdi+24]
+ adcx r12, rax
+ mulx rax, rbx, QWORD PTR [rbp]
+ adox r11, rbx
+ adox r12, rax
+ ; A[3] * B[2]
+ mulx rax, rdx, QWORD PTR [rbp+16]
+ adcx r13, rdx
+ ; A[2] * B[3]
+ mov rdx, QWORD PTR [rbp+24]
+ adcx r14, rax
+ mulx rdx, rax, QWORD PTR [rdi+16]
+ adcx r15, rsi
+ adox r13, rax
+ adox r14, rdx
+ adox r15, rsi
+ ; Start Reduction
+ mov rbx, 14758798090332847183
+ ; A[0]
+ mov rdx, rbx
+ imul rdx, r8
+ mov rax, 17562291160714782033
+ xor rbp, rbp
+ mulx rdi, rsi, rax
+ mov rax, 13611842547513532036
+ adcx r8, rsi
+ adox r9, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744073709551615
+ adcx r9, rsi
+ adox r10, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744069414584320
+ adcx r10, rsi
+ adox r11, rdi
+ mulx rdi, rsi, rax
+ adcx r11, rsi
+ adox r12, rdi
+ adcx r12, rbp
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[1]
+ mov rdx, rbx
+ imul rdx, r9
+ mov rax, 17562291160714782033
+ xor rbp, rbp
+ mulx rdi, rsi, rax
+ mov rax, 13611842547513532036
+ adcx r9, rsi
+ adox r10, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744073709551615
+ adcx r10, rsi
+ adox r11, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744069414584320
+ adcx r11, rsi
+ adox r12, rdi
+ mulx rdi, rsi, rax
+ adcx r12, rsi
+ adox r13, rdi
+ adcx r13, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[2]
+ mov rdx, rbx
+ imul rdx, r10
+ mov rax, 17562291160714782033
+ xor rbp, rbp
+ mulx rdi, rsi, rax
+ mov rax, 13611842547513532036
+ adcx r10, rsi
+ adox r11, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744073709551615
+ adcx r11, rsi
+ adox r12, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744069414584320
+ adcx r12, rsi
+ adox r13, rdi
+ mulx rdi, rsi, rax
+ adcx r13, rsi
+ adox r14, rdi
+ adcx r14, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[3]
+ mov rdx, rbx
+ imul rdx, r11
+ mov rax, 17562291160714782033
+ xor rbp, rbp
+ mulx rdi, rsi, rax
+ mov rax, 13611842547513532036
+ adcx r11, rsi
+ adox r12, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744073709551615
+ adcx r12, rsi
+ adox r13, rdi
+ mulx rdi, rsi, rax
+ mov rax, 18446744069414584320
+ adcx r13, rsi
+ adox r14, rdi
+ mulx rdi, rsi, rax
+ adcx r14, rsi
+ adox r15, rdi
+ adcx r15, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ neg r8
+ mov rax, 17562291160714782033
+ mov rbx, 13611842547513532036
+ and rax, r8
+ mov rbp, 18446744069414584320
+ and rbx, r8
+ and rbp, r8
+ sub r12, rax
+ sbb r13, rbx
+ mov QWORD PTR [rcx], r12
+ sbb r14, r8
+ mov QWORD PTR [rcx+8], r13
+ sbb r15, rbp
+ mov QWORD PTR [rcx+16], r14
+ mov QWORD PTR [rcx+24], r15
+ pop rsi
+ pop rdi
+ pop rbp
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbx
+ ret
+sp_256_mont_mul_order_avx2_4 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
+; *
+; * r Result of squaring.
+; * a Number to square in Montogmery form.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mont_sqr_order_avx2_4 PROC
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov rax, rdx
+ ; A[0] * A[1]
+ mov rdx, QWORD PTR [rax]
+ mov r15, QWORD PTR [rax+16]
+ mulx r10, r9, QWORD PTR [rax+8]
+ ; A[0] * A[3]
+ mulx r12, r11, QWORD PTR [rax+24]
+ ; A[2] * A[1]
+ mov rdx, r15
+ mulx rbx, rsi, QWORD PTR [rax+8]
+ ; A[2] * A[3]
+ mulx r14, r13, QWORD PTR [rax+24]
+ xor r15, r15
+ adox r11, rsi
+ adox r12, rbx
+ ; A[2] * A[0]
+ mulx rbx, rsi, QWORD PTR [rax]
+ ; A[1] * A[3]
+ mov rdx, QWORD PTR [rax+8]
+ adox r13, r15
+ mulx r8, rdi, QWORD PTR [rax+24]
+ adcx r10, rsi
+ adox r14, r15
+ adcx r11, rbx
+ adcx r12, rdi
+ adcx r13, r8
+ adcx r14, r15
+ ; Double with Carry Flag
+ xor r15, r15
+ ; A[0] * A[0]
+ mov rdx, QWORD PTR [rax]
+ mulx rdi, r8, rdx
+ adcx r9, r9
+ adcx r10, r10
+ adox r9, rdi
+ ; A[1] * A[1]
+ mov rdx, QWORD PTR [rax+8]
+ mulx rbx, rsi, rdx
+ adcx r11, r11
+ adox r10, rsi
+ ; A[2] * A[2]
+ mov rdx, QWORD PTR [rax+16]
+ mulx rsi, rdi, rdx
+ adcx r12, r12
+ adox r11, rbx
+ adcx r13, r13
+ adox r12, rdi
+ adcx r14, r14
+ ; A[3] * A[3]
+ mov rdx, QWORD PTR [rax+24]
+ mulx rbx, rdi, rdx
+ adox r13, rsi
+ adcx r15, r15
+ adox r14, rdi
+ adox r15, rbx
+ ; Start Reduction
+ mov rbx, 14758798090332847183
+ ; A[0]
+ mov rdx, rbx
+ imul rdx, r8
+ mov rdi, 17562291160714782033
+ xor rbp, rbp
+ mulx rax, rsi, rdi
+ mov rdi, 13611842547513532036
+ adcx r8, rsi
+ adox r9, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744073709551615
+ adcx r9, rsi
+ adox r10, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744069414584320
+ adcx r10, rsi
+ adox r11, rax
+ mulx rax, rsi, rdi
+ adcx r11, rsi
+ adox r12, rax
+ adcx r12, rbp
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[1]
+ mov rdx, rbx
+ imul rdx, r9
+ mov rdi, 17562291160714782033
+ xor rbp, rbp
+ mulx rax, rsi, rdi
+ mov rdi, 13611842547513532036
+ adcx r9, rsi
+ adox r10, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744073709551615
+ adcx r10, rsi
+ adox r11, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744069414584320
+ adcx r11, rsi
+ adox r12, rax
+ mulx rax, rsi, rdi
+ adcx r12, rsi
+ adox r13, rax
+ adcx r13, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[2]
+ mov rdx, rbx
+ imul rdx, r10
+ mov rdi, 17562291160714782033
+ xor rbp, rbp
+ mulx rax, rsi, rdi
+ mov rdi, 13611842547513532036
+ adcx r10, rsi
+ adox r11, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744073709551615
+ adcx r11, rsi
+ adox r12, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744069414584320
+ adcx r12, rsi
+ adox r13, rax
+ mulx rax, rsi, rdi
+ adcx r13, rsi
+ adox r14, rax
+ adcx r14, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ ; A[3]
+ mov rdx, rbx
+ imul rdx, r11
+ mov rdi, 17562291160714782033
+ xor rbp, rbp
+ mulx rax, rsi, rdi
+ mov rdi, 13611842547513532036
+ adcx r11, rsi
+ adox r12, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744073709551615
+ adcx r12, rsi
+ adox r13, rax
+ mulx rax, rsi, rdi
+ mov rdi, 18446744069414584320
+ adcx r13, rsi
+ adox r14, rax
+ mulx rax, rsi, rdi
+ adcx r14, rsi
+ adox r15, rax
+ adcx r15, r8
+ mov r8, rbp
+ ; carry
+ adox r8, rbp
+ adcx r8, rbp
+ neg r8
+ mov rdi, 17562291160714782033
+ mov rbx, 13611842547513532036
+ and rdi, r8
+ mov rbp, 18446744069414584320
+ and rbx, r8
+ and rbp, r8
+ sub r12, rdi
+ sbb r13, rbx
+ mov QWORD PTR [rcx], r12
+ sbb r14, r8
+ mov QWORD PTR [rcx+8], r13
+ sbb r15, rbp
+ mov QWORD PTR [rcx+16], r14
+ mov QWORD PTR [rcx+24], r15
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ ret
+sp_256_mont_sqr_order_avx2_4 ENDP
+_text ENDS
+ENDIF
+; /* Non-constant time modular inversion.
+; *
+; * @param [out] r Resulting number.
+; * @param [in] a Number to invert.
+; * @param [in] m Modulus.
+; * @return MP_OKAY on success.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mod_inv_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ sub rsp, 513
+ mov r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [r8+24]
+ mov r13, QWORD PTR [rdx]
+ mov r14, QWORD PTR [rdx+8]
+ mov r15, QWORD PTR [rdx+16]
+ mov rdi, QWORD PTR [rdx+24]
+ mov rsi, 0
+ test r13b, 1
+ jnz L_256_mod_inv_4_v_even_end
+L_256_mod_inv_4_v_even_start:
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shrd r15, rdi, 1
+ shr rdi, 1
+ mov BYTE PTR [rsp+rsi], 1
+ inc rsi
+ test r13b, 1
+ jz L_256_mod_inv_4_v_even_start
+L_256_mod_inv_4_v_even_end:
+L_256_mod_inv_4_uv_start:
+ cmp r12, rdi
+ jb L_256_mod_inv_4_uv_v
+ ja L_256_mod_inv_4_uv_u
+ cmp r11, r15
+ jb L_256_mod_inv_4_uv_v
+ ja L_256_mod_inv_4_uv_u
+ cmp r10, r14
+ jb L_256_mod_inv_4_uv_v
+ ja L_256_mod_inv_4_uv_u
+ cmp r9, r13
+ jb L_256_mod_inv_4_uv_v
+L_256_mod_inv_4_uv_u:
+ mov BYTE PTR [rsp+rsi], 2
+ inc rsi
+ sub r9, r13
+ sbb r10, r14
+ sbb r11, r15
+ sbb r12, rdi
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shrd r11, r12, 1
+ shr r12, 1
+ test r8b, 1
+ jnz L_256_mod_inv_4_usubv_even_end
+L_256_mod_inv_4_usubv_even_start:
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shrd r11, r12, 1
+ shr r12, 1
+ mov BYTE PTR [rsp+rsi], 0
+ inc rsi
+ test r8b, 1
+ jz L_256_mod_inv_4_usubv_even_start
+L_256_mod_inv_4_usubv_even_end:
+ cmp r9, 1
+ jne L_256_mod_inv_4_uv_start
+ mov rdx, r10
+ or rdx, r11
+ jne L_256_mod_inv_4_uv_start
+ or rdx, r12
+ jne L_256_mod_inv_4_uv_start
+ mov al, 1
+ jmp L_256_mod_inv_4_uv_end
+L_256_mod_inv_4_uv_v:
+ mov BYTE PTR [rsp+rsi], 3
+ inc rsi
+ sub r13, r9
+ sbb r14, r10
+ sbb r15, r11
+ sbb rdi, r12
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shrd r15, rdi, 1
+ shr rdi, 1
+ test r13b, 1
+ jnz L_256_mod_inv_4_vsubu_even_end
+L_256_mod_inv_4_vsubu_even_start:
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shrd r15, rdi, 1
+ shr rdi, 1
+ mov BYTE PTR [rsp+rsi], 1
+ inc rsi
+ test r13b, 1
+ jz L_256_mod_inv_4_vsubu_even_start
+L_256_mod_inv_4_vsubu_even_end:
+ cmp r13, 1
+ jne L_256_mod_inv_4_uv_start
+ mov rdx, r14
+ or rdx, r15
+ jne L_256_mod_inv_4_uv_start
+ or rdx, rdi
+ jne L_256_mod_inv_4_uv_start
+ mov al, 0
+L_256_mod_inv_4_uv_end:
+ mov r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [r8+24]
+ mov r13, 1
+ xor r14, r14
+ xor r15, r15
+ xor rdi, rdi
+ mov BYTE PTR [rsp+rsi], 7
+ mov dl, BYTE PTR [rsp]
+ mov rsi, 1
+ cmp dl, 1
+ je L_256_mod_inv_4_op_div2_d
+ jl L_256_mod_inv_4_op_div2_b
+ cmp dl, 3
+ je L_256_mod_inv_4_op_d_sub_b
+ jl L_256_mod_inv_4_op_b_sub_d
+ jmp L_256_mod_inv_4_op_end
+L_256_mod_inv_4_op_b_sub_d:
+ sub r9, r13
+ sbb r10, r14
+ sbb r11, r15
+ sbb r12, rdi
+ jnc L_256_mod_inv_4_op_div2_b
+ add r9, QWORD PTR [r8]
+ adc r10, QWORD PTR [r8+8]
+ adc r11, QWORD PTR [r8+16]
+ adc r12, QWORD PTR [r8+24]
+L_256_mod_inv_4_op_div2_b:
+ test r8b, 1
+ mov rdx, 0
+ jz L_256_mod_inv_4_op_div2_b_mod
+ add r9, QWORD PTR [r8]
+ adc r10, QWORD PTR [r8+8]
+ adc r11, QWORD PTR [r8+16]
+ adc r12, QWORD PTR [r8+24]
+ adc rdx, 0
+L_256_mod_inv_4_op_div2_b_mod:
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shrd r11, r12, 1
+ shrd r12, rdx, 1
+ mov dl, BYTE PTR [rsp+rsi]
+ inc rsi
+ cmp dl, 1
+ je L_256_mod_inv_4_op_div2_d
+ jl L_256_mod_inv_4_op_div2_b
+ cmp dl, 3
+ je L_256_mod_inv_4_op_d_sub_b
+ jl L_256_mod_inv_4_op_b_sub_d
+ jmp L_256_mod_inv_4_op_end
+L_256_mod_inv_4_op_d_sub_b:
+ sub r13, r9
+ sbb r14, r10
+ sbb r15, r11
+ sbb rdi, r12
+ jnc L_256_mod_inv_4_op_div2_d
+ add r13, QWORD PTR [r8]
+ adc r14, QWORD PTR [r8+8]
+ adc r15, QWORD PTR [r8+16]
+ adc rdi, QWORD PTR [r8+24]
+L_256_mod_inv_4_op_div2_d:
+ test r13b, 1
+ mov rdx, 0
+ jz L_256_mod_inv_4_op_div2_d_mod
+ add r13, QWORD PTR [r8]
+ adc r14, QWORD PTR [r8+8]
+ adc r15, QWORD PTR [r8+16]
+ adc rdi, QWORD PTR [r8+24]
+ adc rdx, 0
+L_256_mod_inv_4_op_div2_d_mod:
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shrd r15, rdi, 1
+ shrd rdi, rdx, 1
+ mov dl, BYTE PTR [rsp+rsi]
+ inc rsi
+ cmp dl, 1
+ je L_256_mod_inv_4_op_div2_d
+ jl L_256_mod_inv_4_op_div2_b
+ cmp dl, 3
+ je L_256_mod_inv_4_op_d_sub_b
+ jl L_256_mod_inv_4_op_b_sub_d
+L_256_mod_inv_4_op_end:
+ cmp al, 1
+ jne L_256_mod_inv_4_store_d
+ mov QWORD PTR [rcx], r9
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ jmp L_256_mod_inv_4_store_end
+L_256_mod_inv_4_store_d:
+ mov QWORD PTR [rcx], r13
+ mov QWORD PTR [rcx+8], r14
+ mov QWORD PTR [rcx+16], r15
+ mov QWORD PTR [rcx+24], rdi
+L_256_mod_inv_4_store_end:
+ add rsp, 513
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mod_inv_4 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_order DWORD 6497617,32001851,62711546,67108863,67043328,0,0,0,41070783,45522014,67108863,1023,4194303,0,0,0
+ptr_L_sp256_mod_inv_avx2_4_order QWORD L_sp256_mod_inv_avx2_4_order
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_one QWORD 1, 0,
+ 0, 0
+ptr_L_sp256_mod_inv_avx2_4_one QWORD L_sp256_mod_inv_avx2_4_one
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_all_one DWORD 1,1,1,1,1,1,1,1
+ptr_L_sp256_mod_inv_avx2_4_all_one QWORD L_sp256_mod_inv_avx2_4_all_one
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_mask01111 DWORD 0,1,1,1,1,0,0,0
+ptr_L_sp256_mod_inv_avx2_4_mask01111 QWORD L_sp256_mod_inv_avx2_4_mask01111
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_down_one_dword DWORD 1,2,3,4,5,6,7,7
+ptr_L_sp256_mod_inv_avx2_4_down_one_dword QWORD L_sp256_mod_inv_avx2_4_down_one_dword
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_neg DWORD 0,0,0,0,2147483648,0,0,0
+ptr_L_sp256_mod_inv_avx2_4_neg QWORD L_sp256_mod_inv_avx2_4_neg
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_up_one_dword DWORD 7,0,1,2,3,7,7,7
+ptr_L_sp256_mod_inv_avx2_4_up_one_dword QWORD L_sp256_mod_inv_avx2_4_up_one_dword
+_DATA ENDS
+_DATA SEGMENT
+ALIGN 16
+L_sp256_mod_inv_avx2_4_mask26 DWORD 67108863,67108863,67108863,67108863,67108863,0,0,0
+ptr_L_sp256_mod_inv_avx2_4_mask26 QWORD L_sp256_mod_inv_avx2_4_mask26
+_DATA ENDS
+; /* Non-constant time modular inversion.
+; *
+; * @param [out] r Resulting number.
+; * @param [in] a Number to invert.
+; * @param [in] m Modulus.
+; * @return MP_OKAY on success.
+; */
+_text SEGMENT READONLY PARA
+sp_256_mod_inv_avx2_4 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov rax, QWORD PTR [r8]
+ mov r9, QWORD PTR [r8+8]
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ mov r12, QWORD PTR [rdx]
+ mov r13, QWORD PTR [rdx+8]
+ mov r14, QWORD PTR [rdx+16]
+ mov r15, QWORD PTR [rdx+24]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_order
+ vmovupd ymm6, [rbx]
+ vmovupd ymm7, [rbx+32]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_one
+ vmovupd ymm8, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_mask01111
+ vmovupd ymm9, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_all_one
+ vmovupd ymm10, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_down_one_dword
+ vmovupd ymm11, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_neg
+ vmovupd ymm12, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_up_one_dword
+ vmovupd ymm13, [rbx]
+ mov rbx, ptr_L_sp256_mod_inv_avx2_4_mask26
+ vmovupd ymm14, [rbx]
+ vpxor xmm0, xmm0, xmm0
+ vpxor xmm1, xmm1, xmm1
+ vmovdqu ymm2, ymm8
+ vpxor xmm3, xmm3, xmm3
+ test r12b, 1
+ jnz L_256_mod_inv_avx2_4_v_even_end
+L_256_mod_inv_avx2_4_v_even_start:
+ shrd r12, r13, 1
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shr r15, 1
+ vptest ymm2, ymm8
+ jz L_256_mod_inv_avx2_4_v_even_shr1
+ vpaddd ymm2, ymm2, ymm6
+ vpaddd ymm3, ymm3, ymm7
+L_256_mod_inv_avx2_4_v_even_shr1:
+ vpand ymm4, ymm2, ymm9
+ vpand ymm5, ymm3, ymm10
+ vpermd ymm4, ymm11, ymm4
+ vpsrad ymm2, ymm2, 1
+ vpsrad ymm3, ymm3, 1
+ vpslld ymm5, ymm5, 25
+ vpslld xmm4, xmm4, 25
+ vpaddd ymm2, ymm2, ymm5
+ vpaddd ymm3, ymm3, ymm4
+ test r12b, 1
+ jz L_256_mod_inv_avx2_4_v_even_start
+L_256_mod_inv_avx2_4_v_even_end:
+L_256_mod_inv_avx2_4_uv_start:
+ cmp r11, r15
+ jb L_256_mod_inv_avx2_4_uv_v
+ ja L_256_mod_inv_avx2_4_uv_u
+ cmp r10, r14
+ jb L_256_mod_inv_avx2_4_uv_v
+ ja L_256_mod_inv_avx2_4_uv_u
+ cmp r9, r13
+ jb L_256_mod_inv_avx2_4_uv_v
+ ja L_256_mod_inv_avx2_4_uv_u
+ cmp rax, r12
+ jb L_256_mod_inv_avx2_4_uv_v
+L_256_mod_inv_avx2_4_uv_u:
+ sub rax, r12
+ sbb r9, r13
+ vpsubd ymm0, ymm0, ymm2
+ sbb r10, r14
+ vpsubd ymm1, ymm1, ymm3
+ sbb r11, r15
+ vptest ymm1, ymm12
+ jz L_256_mod_inv_avx2_4_usubv_done_neg
+ vpaddd ymm0, ymm0, ymm6
+ vpaddd ymm1, ymm1, ymm7
+L_256_mod_inv_avx2_4_usubv_done_neg:
+L_256_mod_inv_avx2_4_usubv_shr1:
+ shrd rax, r9, 1
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shr r11, 1
+ vptest ymm0, ymm8
+ jz L_256_mod_inv_avx2_4_usubv_sub_shr1
+ vpaddd ymm0, ymm0, ymm6
+ vpaddd ymm1, ymm1, ymm7
+L_256_mod_inv_avx2_4_usubv_sub_shr1:
+ vpand ymm4, ymm0, ymm9
+ vpand ymm5, ymm1, ymm10
+ vpermd ymm4, ymm11, ymm4
+ vpsrad ymm0, ymm0, 1
+ vpsrad ymm1, ymm1, 1
+ vpslld ymm5, ymm5, 25
+ vpslld xmm4, xmm4, 25
+ vpaddd ymm0, ymm0, ymm5
+ vpaddd ymm1, ymm1, ymm4
+ test al, 1
+ jz L_256_mod_inv_avx2_4_usubv_shr1
+ cmp rax, 1
+ jne L_256_mod_inv_avx2_4_uv_start
+ mov rdx, r9
+ or rdx, r10
+ jne L_256_mod_inv_avx2_4_uv_start
+ or rdx, r11
+ jne L_256_mod_inv_avx2_4_uv_start
+ vpsrad ymm5, ymm1, 26
+ vpsrad ymm4, ymm0, 26
+ vpermd ymm5, ymm13, ymm5
+ vpand ymm0, ymm0, ymm14
+ vpand ymm1, ymm1, ymm14
+ vpaddd ymm0, ymm0, ymm5
+ vpaddd ymm1, ymm1, ymm4
+ vpextrd eax, xmm0, 0
+ vpextrd r10d, xmm0, 1
+ vpextrd r12d, xmm0, 2
+ vpextrd r14d, xmm0, 3
+ vextracti128 xmm0, ymm0, 1
+ vpextrd r9d, xmm1, 0
+ vpextrd r11d, xmm1, 1
+ vpextrd r13d, xmm1, 2
+ vpextrd r15d, xmm1, 3
+ vextracti128 xmm1, ymm1, 1
+ vpextrd edi, xmm0, 0
+ vpextrd esi, xmm1, 0
+ jmp L_256_mod_inv_avx2_4_store_done
+L_256_mod_inv_avx2_4_uv_v:
+ sub r12, rax
+ sbb r13, r9
+ vpsubd ymm2, ymm2, ymm0
+ sbb r14, r10
+ vpsubd ymm3, ymm3, ymm1
+ sbb r15, r11
+ vptest ymm3, ymm12
+ jz L_256_mod_inv_avx2_4_vsubu_done_neg
+ vpaddd ymm2, ymm2, ymm6
+ vpaddd ymm3, ymm3, ymm7
+L_256_mod_inv_avx2_4_vsubu_done_neg:
+L_256_mod_inv_avx2_4_vsubu_shr1:
+ shrd r12, r13, 1
+ shrd r13, r14, 1
+ shrd r14, r15, 1
+ shr r15, 1
+ vptest ymm2, ymm8
+ jz L_256_mod_inv_avx2_4_vsubu_sub_shr1
+ vpaddd ymm2, ymm2, ymm6
+ vpaddd ymm3, ymm3, ymm7
+L_256_mod_inv_avx2_4_vsubu_sub_shr1:
+ vpand ymm4, ymm2, ymm9
+ vpand ymm5, ymm3, ymm10
+ vpermd ymm4, ymm11, ymm4
+ vpsrad ymm2, ymm2, 1
+ vpsrad ymm3, ymm3, 1
+ vpslld ymm5, ymm5, 25
+ vpslld xmm4, xmm4, 25
+ vpaddd ymm2, ymm2, ymm5
+ vpaddd ymm3, ymm3, ymm4
+ test r12b, 1
+ jz L_256_mod_inv_avx2_4_vsubu_shr1
+ cmp r12, 1
+ jne L_256_mod_inv_avx2_4_uv_start
+ mov rdx, r13
+ or rdx, r14
+ jne L_256_mod_inv_avx2_4_uv_start
+ or rdx, r15
+ jne L_256_mod_inv_avx2_4_uv_start
+ vpsrad ymm5, ymm3, 26
+ vpsrad ymm4, ymm2, 26
+ vpermd ymm5, ymm13, ymm5
+ vpand ymm2, ymm2, ymm14
+ vpand ymm3, ymm3, ymm14
+ vpaddd ymm2, ymm2, ymm5
+ vpaddd ymm3, ymm3, ymm4
+ vpextrd eax, xmm2, 0
+ vpextrd r10d, xmm2, 1
+ vpextrd r12d, xmm2, 2
+ vpextrd r14d, xmm2, 3
+ vextracti128 xmm2, ymm2, 1
+ vpextrd r9d, xmm3, 0
+ vpextrd r11d, xmm3, 1
+ vpextrd r13d, xmm3, 2
+ vpextrd r15d, xmm3, 3
+ vextracti128 xmm3, ymm3, 1
+ vpextrd edi, xmm2, 0
+ vpextrd esi, xmm3, 0
+L_256_mod_inv_avx2_4_store_done:
+ shl r9, 26
+ add rax, r9
+ shl r11, 26
+ add r10, r11
+ shl r13, 26
+ add r12, r13
+ shl r15, 26
+ add r14, r15
+ shl rsi, 26
+ add rdi, rsi
+ mov r9, r10
+ mov r11, r12
+ mov r13, r14
+ shl r9, 52
+ sar r10, 12
+ shl r11, 40
+ sar r12, 24
+ shl r13, 28
+ sar r14, 36
+ shl rdi, 16
+ add rax, r9
+ adc r10, r11
+ adc r12, r13
+ adc r14, rdi
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r14
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_256_mod_inv_avx2_4 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFDEF WOLFSSL_SP_384
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mul_6 PROC
+ push r12
+ mov r9, rdx
+ sub rsp, 48
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ mov QWORD PTR [rsp], rax
+ mov r11, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+8], r11
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+16], r12
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+24], r10
+ ; A[0] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+32], r11
+ ; A[0] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+40], r12
+ ; A[1] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+8]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+48], r10
+ ; A[2] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+16]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+56], r11
+ ; A[3] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+24]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+64], r12
+ ; A[4] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+32]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+72], r10
+ ; A[5] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ mov QWORD PTR [rcx+80], r11
+ mov QWORD PTR [rcx+88], r12
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r10, QWORD PTR [rsp+16]
+ mov r11, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ add rsp, 48
+ pop r12
+ ret
+sp_384_mul_6 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_sqr_6 PROC
+ push r12
+ push r13
+ push r14
+ mov r8, rdx
+ sub rsp, 48
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ xor r11, r11
+ mov QWORD PTR [rsp], rax
+ mov r10, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+8], r10
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+16], r11
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+8]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+24], r9
+ ; A[0] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+8]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+32], r10
+ ; A[0] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+40], r11
+ ; A[1] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+16]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+48], r9
+ ; A[2] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+16]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[3] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+24]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rcx+56], r10
+ ; A[3] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+24]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[4] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+64], r11
+ ; A[4] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+32]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+72], r9
+ ; A[5] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r12, QWORD PTR [rsp+16]
+ mov r13, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ add rsp, 48
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_sqr_6 ENDP
+_text ENDS
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_add_6 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov QWORD PTR [rcx+40], r10
+ adc rax, 0
+ ret
+sp_384_add_6 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_sub_6 PROC
+ push r12
+ push r13
+ push r14
+ xor rax, rax
+ mov r9, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ mov r13, QWORD PTR [rdx+32]
+ mov r14, QWORD PTR [rdx+40]
+ sub r9, QWORD PTR [r8]
+ sbb r10, QWORD PTR [r8+8]
+ sbb r11, QWORD PTR [r8+16]
+ sbb r12, QWORD PTR [r8+24]
+ sbb r13, QWORD PTR [r8+32]
+ sbb r14, QWORD PTR [r8+40]
+ mov QWORD PTR [rcx], r9
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov QWORD PTR [rcx+32], r13
+ mov QWORD PTR [rcx+40], r14
+ sbb rax, 0
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_sub_6 ENDP
+_text ENDS
+; /* Conditionally copy a into r using the mask m.
+; * m is -1 to copy and 0 when not.
+; *
+; * r A single precision number to copy over.
+; * a A single precision number to copy.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_384_cond_copy_6 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [rcx+16]
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rcx+32]
+ mov r13, QWORD PTR [rcx+40]
+ xor rax, QWORD PTR [rdx]
+ xor r9, QWORD PTR [rdx+8]
+ xor r10, QWORD PTR [rdx+16]
+ xor r11, QWORD PTR [rdx+24]
+ xor r12, QWORD PTR [rdx+32]
+ xor r13, QWORD PTR [rdx+40]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ and r12, r8
+ and r13, r8
+ xor QWORD PTR [rcx], rax
+ xor QWORD PTR [rcx+8], r9
+ xor QWORD PTR [rcx+16], r10
+ xor QWORD PTR [rcx+24], r11
+ xor QWORD PTR [rcx+32], r12
+ xor QWORD PTR [rcx+40], r13
+ pop r13
+ pop r12
+ ret
+sp_384_cond_copy_6 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_384_cond_sub_6 PROC
+ sub rsp, 48
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov QWORD PTR [rcx+40], r11
+ sbb rax, 0
+ add rsp, 48
+ ret
+sp_384_cond_sub_6 ENDP
+_text ENDS
+; /* Reduce the number back to 384 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mont_reduce_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r12, QWORD PTR [rcx]
+ mov r13, QWORD PTR [rcx+8]
+ mov r14, QWORD PTR [rcx+16]
+ mov r15, QWORD PTR [rcx+24]
+ mov rdi, QWORD PTR [rcx+32]
+ mov rsi, QWORD PTR [rcx+40]
+ xor r11, r11
+ ; a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp)
+ mov rbx, QWORD PTR [rcx+48]
+ mov rbp, QWORD PTR [rcx+56]
+ mov rdx, r12
+ mov rax, r13
+ shld rax, rdx, 32
+ shl rdx, 32
+ add rdx, r12
+ adc rax, r13
+ add rax, r12
+ mov r8, rdx
+ mov r9, rax
+ mov r10, rax
+ shld r9, r8, 32
+ shl r8, 32
+ shr r10, 32
+ add r12, r8
+ adc r13, r9
+ adc r14, r10
+ adc r15, 0
+ adc rdi, 0
+ adc rsi, 0
+ adc rbx, rdx
+ adc rbp, rax
+ adc r11, 0
+ add r8, rax
+ adc r9, rdx
+ adc r10, rax
+ mov rax, 0
+ adc rax, 0
+ sub r14, r9
+ sbb r15, r10
+ sbb rdi, rax
+ sbb rsi, 0
+ sbb rbx, 0
+ sbb rbp, 0
+ sbb r11, 0
+ ; a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp)
+ mov r12, QWORD PTR [rcx+64]
+ mov r13, QWORD PTR [rcx+72]
+ mov rdx, r14
+ mov rax, r15
+ shld rax, rdx, 32
+ shl rdx, 32
+ add rdx, r14
+ adc rax, r15
+ add rax, r14
+ mov r8, rdx
+ mov r9, rax
+ mov r10, rax
+ shld r9, r8, 32
+ shl r8, 32
+ shr r10, 32
+ add r12, r11
+ adc r13, 0
+ mov r11, 0
+ adc r11, 0
+ add r14, r8
+ adc r15, r9
+ adc rdi, r10
+ adc rsi, 0
+ adc rbx, 0
+ adc rbp, 0
+ adc r12, rdx
+ adc r13, rax
+ adc r11, 0
+ add r8, rax
+ adc r9, rdx
+ adc r10, rax
+ mov rax, 0
+ adc rax, 0
+ sub rdi, r9
+ sbb rsi, r10
+ sbb rbx, rax
+ sbb rbp, 0
+ sbb r12, 0
+ sbb r13, 0
+ sbb r11, 0
+ ; a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp)
+ mov r14, QWORD PTR [rcx+80]
+ mov r15, QWORD PTR [rcx+88]
+ mov rdx, rdi
+ mov rax, rsi
+ shld rax, rdx, 32
+ shl rdx, 32
+ add rdx, rdi
+ adc rax, rsi
+ add rax, rdi
+ mov r8, rdx
+ mov r9, rax
+ mov r10, rax
+ shld r9, r8, 32
+ shl r8, 32
+ shr r10, 32
+ add r14, r11
+ adc r15, 0
+ mov r11, 0
+ adc r11, 0
+ add rdi, r8
+ adc rsi, r9
+ adc rbx, r10
+ adc rbp, 0
+ adc r12, 0
+ adc r13, 0
+ adc r14, rdx
+ adc r15, rax
+ adc r11, 0
+ add r8, rax
+ adc r9, rdx
+ adc r10, rax
+ mov rax, 0
+ adc rax, 0
+ sub rbx, r9
+ sbb rbp, r10
+ sbb r12, rax
+ sbb r13, 0
+ sbb r14, 0
+ sbb r15, 0
+ sbb r11, 0
+ ; Subtract mod if carry
+ neg r11
+ mov r10, 18446744073709551614
+ mov r8, r11
+ mov r9, r11
+ shr r8, 32
+ shl r9, 32
+ and r10, r11
+ sub rbx, r8
+ sbb rbp, r9
+ sbb r12, r10
+ sbb r13, r11
+ sbb r14, r11
+ sbb r15, r11
+ mov QWORD PTR [rcx], rbx
+ mov QWORD PTR [rcx+8], rbp
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ mov QWORD PTR [rcx+32], r14
+ mov QWORD PTR [rcx+40], r15
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_mont_reduce_6 ENDP
+_text ENDS
+; /* Reduce the number back to 384 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mont_reduce_order_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 6
+ mov r10, 6
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_384_mont_loop_order_6:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc QWORD PTR [rcx+48], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_384_mont_loop_order_6
+ mov QWORD PTR [rcx], r15
+ mov QWORD PTR [rcx+8], rdi
+ neg rsi
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 48
+ call sp_384_cond_sub_6
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_mont_reduce_order_6 ENDP
+_text ENDS
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_384_cmp_6 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_384_cmp_6 ENDP
+_text ENDS
+; /* Add a to a into r. (r = a + a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_dbl_6 PROC
+ mov r8, QWORD PTR [rdx]
+ xor rax, rax
+ add r8, r8
+ mov r9, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r8
+ adc r9, r9
+ mov r8, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r9
+ adc r8, r8
+ mov r9, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r8
+ adc r9, r9
+ mov QWORD PTR [rcx+40], r9
+ adc rax, 0
+ ret
+sp_384_dbl_6 ENDP
+_text ENDS
+; /* Conditionally add a and b using the mask m.
+; * m is -1 to add and 0 when not.
+; *
+; * r A single precision number representing conditional add result.
+; * a A single precision number to add with.
+; * b A single precision number to add.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_384_cond_add_6 PROC
+ sub rsp, 48
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ add r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ adc r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ adc r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ adc r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ adc r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ adc r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov QWORD PTR [rcx+40], r11
+ adc rax, 0
+ add rsp, 48
+ ret
+sp_384_cond_add_6 ENDP
+_text ENDS
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_384_div2_6 PROC
+ push r12
+ push r13
+ sub rsp, 48
+ mov r13, QWORD PTR [rdx]
+ xor r12, r12
+ mov rax, r13
+ and r13, 1
+ neg r13
+ mov r10, QWORD PTR [r8]
+ and r10, r13
+ mov QWORD PTR [rsp], r10
+ mov r10, QWORD PTR [r8+8]
+ and r10, r13
+ mov QWORD PTR [rsp+8], r10
+ mov r10, QWORD PTR [r8+16]
+ and r10, r13
+ mov QWORD PTR [rsp+16], r10
+ mov r10, QWORD PTR [r8+24]
+ and r10, r13
+ mov QWORD PTR [rsp+24], r10
+ mov r10, QWORD PTR [r8+32]
+ and r10, r13
+ mov QWORD PTR [rsp+32], r10
+ mov r10, QWORD PTR [r8+40]
+ and r10, r13
+ mov QWORD PTR [rsp+40], r10
+ add QWORD PTR [rsp], rax
+ mov rax, QWORD PTR [rdx+8]
+ adc QWORD PTR [rsp+8], rax
+ mov rax, QWORD PTR [rdx+16]
+ adc QWORD PTR [rsp+16], rax
+ mov rax, QWORD PTR [rdx+24]
+ adc QWORD PTR [rsp+24], rax
+ mov rax, QWORD PTR [rdx+32]
+ adc QWORD PTR [rsp+32], rax
+ mov rax, QWORD PTR [rdx+40]
+ adc QWORD PTR [rsp+40], rax
+ adc r12, 0
+ mov rax, QWORD PTR [rsp]
+ mov r9, QWORD PTR [rsp+8]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx], rax
+ mov rax, QWORD PTR [rsp+16]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+8], r9
+ mov r9, QWORD PTR [rsp+24]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+16], rax
+ mov rax, QWORD PTR [rsp+32]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+24], r9
+ mov r9, QWORD PTR [rsp+40]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+32], rax
+ shrd r9, r12, 1
+ mov QWORD PTR [rcx+40], r9
+ add rsp, 48
+ pop r13
+ pop r12
+ ret
+sp_384_div2_6 ENDP
+_text ENDS
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible point that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of point to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_point_33_6 PROC
+ mov rax, 1
+ movd xmm13, r8d
+ add rdx, 296
+ movd xmm15, eax
+ mov rax, 32
+ pshufd xmm15, xmm15, 0
+ pshufd xmm13, xmm13, 0
+ pxor xmm14, xmm14
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ pxor xmm4, xmm4
+ pxor xmm5, xmm5
+ movdqa xmm14, xmm15
+L_384_get_point_33_6_start:
+ movdqa xmm12, xmm14
+ paddd xmm14, xmm15
+ pcmpeqd xmm12, xmm13
+ movdqu xmm6, [rdx]
+ movdqu xmm7, [rdx+16]
+ movdqu xmm8, [rdx+32]
+ movdqu xmm9, [rdx+96]
+ movdqu xmm10, [rdx+112]
+ movdqu xmm11, [rdx+128]
+ add rdx, 296
+ pand xmm6, xmm12
+ pand xmm7, xmm12
+ pand xmm8, xmm12
+ pand xmm9, xmm12
+ pand xmm10, xmm12
+ pand xmm11, xmm12
+ por xmm0, xmm6
+ por xmm1, xmm7
+ por xmm2, xmm8
+ por xmm3, xmm9
+ por xmm4, xmm10
+ por xmm5, xmm11
+ dec rax
+ jnz L_384_get_point_33_6_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+32], xmm2
+ movdqu [rcx+96], xmm3
+ movdqu [rcx+112], xmm4
+ movdqu [rcx+128], xmm5
+ mov rax, 1
+ movd xmm13, r8d
+ sub rdx, 9472
+ movd xmm15, eax
+ mov rax, 32
+ pshufd xmm15, xmm15, 0
+ pshufd xmm13, xmm13, 0
+ pxor xmm14, xmm14
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ movdqa xmm14, xmm15
+L_384_get_point_33_6_start_2:
+ movdqa xmm12, xmm14
+ paddd xmm14, xmm15
+ pcmpeqd xmm12, xmm13
+ movdqu xmm6, [rdx+192]
+ movdqu xmm7, [rdx+208]
+ movdqu xmm8, [rdx+224]
+ add rdx, 296
+ pand xmm6, xmm12
+ pand xmm7, xmm12
+ pand xmm8, xmm12
+ por xmm0, xmm6
+ por xmm1, xmm7
+ por xmm2, xmm8
+ dec rax
+ jnz L_384_get_point_33_6_start_2
+ movdqu [rcx+192], xmm0
+ movdqu [rcx+208], xmm1
+ movdqu [rcx+224], xmm2
+ ret
+sp_384_get_point_33_6 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible point that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of point to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_point_33_avx2_6 PROC
+ mov rax, 1
+ movd xmm13, r8d
+ add rdx, 296
+ movd xmm15, eax
+ mov rax, 32
+ vpxor ymm14, ymm14, ymm14
+ vpermd ymm13, ymm14, ymm13
+ vpermd ymm15, ymm14, ymm15
+ vpxor ymm0, ymm0, ymm0
+ vpxor xmm1, xmm1, xmm1
+ vpxor ymm2, ymm2, ymm2
+ vpxor xmm3, xmm3, xmm3
+ vpxor ymm4, ymm4, ymm4
+ vpxor xmm5, xmm5, xmm5
+ vmovdqa ymm14, ymm15
+L_384_get_point_33_avx2_6_start:
+ vpcmpeqd ymm12, ymm14, ymm13
+ vpaddd ymm14, ymm14, ymm15
+ vmovupd ymm6, [rdx]
+ vmovdqu xmm7, OWORD PTR [rdx+32]
+ vmovupd ymm8, [rdx+96]
+ vmovdqu xmm9, OWORD PTR [rdx+128]
+ vmovupd ymm10, [rdx+192]
+ vmovdqu xmm11, OWORD PTR [rdx+224]
+ add rdx, 296
+ vpand ymm6, ymm6, ymm12
+ vpand xmm7, xmm7, xmm12
+ vpand ymm8, ymm8, ymm12
+ vpand xmm9, xmm9, xmm12
+ vpand ymm10, ymm10, ymm12
+ vpand xmm11, xmm11, xmm12
+ vpor ymm0, ymm0, ymm6
+ vpor xmm1, xmm1, xmm7
+ vpor ymm2, ymm2, ymm8
+ vpor xmm3, xmm3, xmm9
+ vpor ymm4, ymm4, ymm10
+ vpor xmm5, xmm5, xmm11
+ dec rax
+ jnz L_384_get_point_33_avx2_6_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovdqu [rcx+32], xmm1
+ vmovupd YMMWORD PTR [rcx+96], ymm2
+ vmovdqu [rcx+128], xmm3
+ vmovupd YMMWORD PTR [rcx+192], ymm4
+ vmovdqu [rcx+224], xmm5
+ ret
+sp_384_get_point_33_avx2_6 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r Result of multiplication.
+; * a First number to multiply.
+; * b Second number to multiply.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mul_avx2_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov rax, rdx
+ sub rsp, 40
+ xor rbx, rbx
+ mov rdx, QWORD PTR [rax]
+ ; A[0] * B[0]
+ mulx r12, r11, QWORD PTR [r8]
+ ; A[0] * B[1]
+ mulx r13, r9, QWORD PTR [r8+8]
+ adcx r12, r9
+ ; A[0] * B[2]
+ mulx r14, r9, QWORD PTR [r8+16]
+ adcx r13, r9
+ ; A[0] * B[3]
+ mulx r15, r9, QWORD PTR [r8+24]
+ adcx r14, r9
+ ; A[0] * B[4]
+ mulx rdi, r9, QWORD PTR [r8+32]
+ adcx r15, r9
+ ; A[0] * B[5]
+ mulx rsi, r9, QWORD PTR [r8+40]
+ adcx rdi, r9
+ adcx rsi, rbx
+ mov QWORD PTR [rsp], r11
+ mov r11, 0
+ adcx r11, rbx
+ xor rbx, rbx
+ mov rdx, QWORD PTR [rax+8]
+ ; A[1] * B[0]
+ mulx r10, r9, QWORD PTR [r8]
+ adcx r12, r9
+ adox r13, r10
+ ; A[1] * B[1]
+ mulx r10, r9, QWORD PTR [r8+8]
+ adcx r13, r9
+ adox r14, r10
+ ; A[1] * B[2]
+ mulx r10, r9, QWORD PTR [r8+16]
+ adcx r14, r9
+ adox r15, r10
+ ; A[1] * B[3]
+ mulx r10, r9, QWORD PTR [r8+24]
+ adcx r15, r9
+ adox rdi, r10
+ ; A[1] * B[4]
+ mulx r10, r9, QWORD PTR [r8+32]
+ adcx rdi, r9
+ adox rsi, r10
+ ; A[1] * B[5]
+ mulx r10, r9, QWORD PTR [r8+40]
+ adcx rsi, r9
+ adox r11, r10
+ adcx r11, rbx
+ mov QWORD PTR [rsp+8], r12
+ mov r12, 0
+ adcx r12, rbx
+ adox r12, rbx
+ xor rbx, rbx
+ mov rdx, QWORD PTR [rax+16]
+ ; A[2] * B[0]
+ mulx r10, r9, QWORD PTR [r8]
+ adcx r13, r9
+ adox r14, r10
+ ; A[2] * B[1]
+ mulx r10, r9, QWORD PTR [r8+8]
+ adcx r14, r9
+ adox r15, r10
+ ; A[2] * B[2]
+ mulx r10, r9, QWORD PTR [r8+16]
+ adcx r15, r9
+ adox rdi, r10
+ ; A[2] * B[3]
+ mulx r10, r9, QWORD PTR [r8+24]
+ adcx rdi, r9
+ adox rsi, r10
+ ; A[2] * B[4]
+ mulx r10, r9, QWORD PTR [r8+32]
+ adcx rsi, r9
+ adox r11, r10
+ ; A[2] * B[5]
+ mulx r10, r9, QWORD PTR [r8+40]
+ adcx r11, r9
+ adox r12, r10
+ adcx r12, rbx
+ mov QWORD PTR [rsp+16], r13
+ mov r13, 0
+ adcx r13, rbx
+ adox r13, rbx
+ xor rbx, rbx
+ mov rdx, QWORD PTR [rax+24]
+ ; A[3] * B[0]
+ mulx r10, r9, QWORD PTR [r8]
+ adcx r14, r9
+ adox r15, r10
+ ; A[3] * B[1]
+ mulx r10, r9, QWORD PTR [r8+8]
+ adcx r15, r9
+ adox rdi, r10
+ ; A[3] * B[2]
+ mulx r10, r9, QWORD PTR [r8+16]
+ adcx rdi, r9
+ adox rsi, r10
+ ; A[3] * B[3]
+ mulx r10, r9, QWORD PTR [r8+24]
+ adcx rsi, r9
+ adox r11, r10
+ ; A[3] * B[4]
+ mulx r10, r9, QWORD PTR [r8+32]
+ adcx r11, r9
+ adox r12, r10
+ ; A[3] * B[5]
+ mulx r10, r9, QWORD PTR [r8+40]
+ adcx r12, r9
+ adox r13, r10
+ adcx r13, rbx
+ mov QWORD PTR [rsp+24], r14
+ mov r14, 0
+ adcx r14, rbx
+ adox r14, rbx
+ xor rbx, rbx
+ mov rdx, QWORD PTR [rax+32]
+ ; A[4] * B[0]
+ mulx r10, r9, QWORD PTR [r8]
+ adcx r15, r9
+ adox rdi, r10
+ ; A[4] * B[1]
+ mulx r10, r9, QWORD PTR [r8+8]
+ adcx rdi, r9
+ adox rsi, r10
+ ; A[4] * B[2]
+ mulx r10, r9, QWORD PTR [r8+16]
+ adcx rsi, r9
+ adox r11, r10
+ ; A[4] * B[3]
+ mulx r10, r9, QWORD PTR [r8+24]
+ adcx r11, r9
+ adox r12, r10
+ ; A[4] * B[4]
+ mulx r10, r9, QWORD PTR [r8+32]
+ adcx r12, r9
+ adox r13, r10
+ ; A[4] * B[5]
+ mulx r10, r9, QWORD PTR [r8+40]
+ adcx r13, r9
+ adox r14, r10
+ adcx r14, rbx
+ mov QWORD PTR [rsp+32], r15
+ mov rdx, QWORD PTR [rax+40]
+ ; A[5] * B[0]
+ mulx r10, r9, QWORD PTR [r8]
+ adcx rdi, r9
+ adox rsi, r10
+ ; A[5] * B[1]
+ mulx r10, r9, QWORD PTR [r8+8]
+ adcx rsi, r9
+ adox r11, r10
+ ; A[5] * B[2]
+ mulx r10, r9, QWORD PTR [r8+16]
+ adcx r11, r9
+ adox r12, r10
+ ; A[5] * B[3]
+ mulx r10, r9, QWORD PTR [r8+24]
+ adcx r12, r9
+ adox r13, r10
+ ; A[5] * B[4]
+ mulx r10, r9, QWORD PTR [r8+32]
+ adcx r13, r9
+ adox r14, r10
+ ; A[5] * B[5]
+ mulx r15, r9, QWORD PTR [r8+40]
+ adcx r14, r9
+ adox r15, rbx
+ adcx r15, rbx
+ mov QWORD PTR [rcx+40], rdi
+ mov QWORD PTR [rcx+48], rsi
+ mov QWORD PTR [rcx+56], r11
+ mov QWORD PTR [rcx+64], r12
+ mov QWORD PTR [rcx+72], r13
+ mov QWORD PTR [rcx+80], r14
+ mov QWORD PTR [rcx+88], r15
+ mov r11, QWORD PTR [rsp]
+ mov r12, QWORD PTR [rsp+8]
+ mov r13, QWORD PTR [rsp+16]
+ mov r14, QWORD PTR [rsp+24]
+ mov r15, QWORD PTR [rsp+32]
+ mov QWORD PTR [rcx], r11
+ mov QWORD PTR [rcx+8], r12
+ mov QWORD PTR [rcx+16], r13
+ mov QWORD PTR [rcx+24], r14
+ mov QWORD PTR [rcx+32], r15
+ add rsp, 40
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_mul_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 384 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mont_reduce_order_avx2_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ mov rax, rdx
+ xor r15, r15
+ mov r14, QWORD PTR [rcx]
+ xor r13, r13
+L_mont_loop_order_avx2_6:
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+8]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+16]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+24]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+32]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+40]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+48]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+48], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+16]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+24]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+32]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+24], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+40]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+32], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+48]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+40], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+56]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+48], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+56], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+24]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+32]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+40]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+48]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+56]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+64]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+64], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+32]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+40]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+48]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+40], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+56]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+48], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+64]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+56], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+72]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+64], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+72], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+40]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+48]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+56]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+64]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+72]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+80]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+80], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ ; mu = a[i] * mp
+ mov rdx, r14
+ mov r11, r14
+ imul rdx, r8
+ xor r13, r13
+ ; a[i+0] += m[0] * mu
+ mulx r10, r9, QWORD PTR [rax]
+ mov r14, QWORD PTR [rcx+48]
+ adcx r11, r9
+ adox r14, r10
+ ; a[i+1] += m[1] * mu
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, QWORD PTR [rcx+56]
+ adcx r14, r9
+ adox r11, r10
+ ; a[i+2] += m[2] * mu
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, QWORD PTR [rcx+64]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+56], r11
+ ; a[i+3] += m[3] * mu
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, QWORD PTR [rcx+72]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+64], r12
+ ; a[i+4] += m[4] * mu
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, QWORD PTR [rcx+80]
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+72], r11
+ ; a[i+5] += m[5] * mu
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, QWORD PTR [rcx+88]
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+80], r12
+ adcx r11, r15
+ mov QWORD PTR [rcx+88], r11
+ mov r15, r13
+ adox r15, r13
+ adcx r15, r13
+ neg r15
+ mov r8, rcx
+ add rcx, 48
+ mov r10, QWORD PTR [rax]
+ mov rdx, r14
+ pext r10, r10, r15
+ sub rdx, r10
+ mov r10, QWORD PTR [rax+8]
+ mov r9, QWORD PTR [rcx+8]
+ pext r10, r10, r15
+ mov QWORD PTR [r8], rdx
+ sbb r9, r10
+ mov rdx, QWORD PTR [rax+16]
+ mov r10, QWORD PTR [rcx+16]
+ pext rdx, rdx, r15
+ mov QWORD PTR [r8+8], r9
+ sbb r10, rdx
+ mov r9, QWORD PTR [rax+24]
+ mov rdx, QWORD PTR [rcx+24]
+ pext r9, r9, r15
+ mov QWORD PTR [r8+16], r10
+ sbb rdx, r9
+ mov r10, QWORD PTR [rax+32]
+ mov r9, QWORD PTR [rcx+32]
+ pext r10, r10, r15
+ mov QWORD PTR [r8+24], rdx
+ sbb r9, r10
+ mov rdx, QWORD PTR [rax+40]
+ mov r10, QWORD PTR [rcx+40]
+ pext rdx, rdx, r15
+ mov QWORD PTR [r8+32], r9
+ sbb r10, rdx
+ mov QWORD PTR [r8+40], r10
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_mont_reduce_order_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r Result of squaring.
+; * a Number to square in Montogmery form.
+; */
+_text SEGMENT READONLY PARA
+sp_384_sqr_avx2_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov rax, rdx
+ push rcx
+ xor rcx, rcx
+ mov rdx, QWORD PTR [rax]
+ mov rsi, QWORD PTR [rax+8]
+ mov rbx, QWORD PTR [rax+16]
+ mov rbp, QWORD PTR [rax+24]
+ ; Diagonal 0
+ ; A[1] * A[0]
+ mulx r11, r10, QWORD PTR [rax+8]
+ ; A[2] * A[0]
+ mulx r12, r8, QWORD PTR [rax+16]
+ adcx r11, r8
+ ; A[3] * A[0]
+ mulx r13, r8, QWORD PTR [rax+24]
+ adcx r12, r8
+ ; A[4] * A[0]
+ mulx r14, r8, QWORD PTR [rax+32]
+ adcx r13, r8
+ ; A[5] * A[0]
+ mulx r15, r8, QWORD PTR [rax+40]
+ adcx r14, r8
+ adcx r15, rcx
+ ; Diagonal 1
+ mov rdx, rsi
+ ; A[2] * A[1]
+ mulx r9, r8, QWORD PTR [rax+16]
+ adcx r12, r8
+ adox r13, r9
+ ; A[3] * A[1]
+ mulx r9, r8, QWORD PTR [rax+24]
+ adcx r13, r8
+ adox r14, r9
+ ; A[4] * A[1]
+ mulx r9, r8, QWORD PTR [rax+32]
+ adcx r14, r8
+ adox r15, r9
+ ; A[5] * A[1]
+ mulx rdi, r8, QWORD PTR [rax+40]
+ adcx r15, r8
+ adox rdi, rcx
+ mov rdx, rbx
+ ; A[5] * A[2]
+ mulx rsi, r8, QWORD PTR [rax+40]
+ adcx rdi, r8
+ adox rsi, rcx
+ adcx rsi, rcx
+ adcx rbx, rcx
+ ; Diagonal 2
+ ; A[3] * A[2]
+ mulx r9, r8, QWORD PTR [rax+24]
+ adcx r14, r8
+ adox r15, r9
+ ; A[4] * A[2]
+ mulx r9, r8, QWORD PTR [rax+32]
+ adcx r15, r8
+ adox rdi, r9
+ mov rdx, rbp
+ ; A[4] * A[3]
+ mulx r9, r8, QWORD PTR [rax+32]
+ adcx rdi, r8
+ adox rsi, r9
+ ; A[5] * A[3]
+ mulx rbx, r8, QWORD PTR [rax+40]
+ adcx rsi, r8
+ adox rbx, rcx
+ mov rdx, QWORD PTR [rax+32]
+ ; A[5] * A[4]
+ mulx rbp, r8, QWORD PTR [rax+40]
+ adcx rbx, r8
+ adox rbp, rcx
+ adcx rbp, rcx
+ adcx rcx, rcx
+ ; Doubling previous result as we add in square words results
+ ; A[0] * A[0]
+ mov rdx, QWORD PTR [rax]
+ mulx r9, r8, rdx
+ pop rdx
+ mov QWORD PTR [rdx], r8
+ adox r10, r10
+ push rdx
+ adcx r10, r9
+ ; A[1] * A[1]
+ mov rdx, QWORD PTR [rax+8]
+ mulx r9, r8, rdx
+ adox r11, r11
+ adcx r11, r8
+ adox r12, r12
+ adcx r12, r9
+ ; A[2] * A[2]
+ mov rdx, QWORD PTR [rax+16]
+ mulx r9, r8, rdx
+ adox r13, r13
+ adcx r13, r8
+ adox r14, r14
+ adcx r14, r9
+ ; A[3] * A[3]
+ mov rdx, QWORD PTR [rax+24]
+ mulx r9, r8, rdx
+ adox r15, r15
+ adcx r15, r8
+ adox rdi, rdi
+ adcx rdi, r9
+ ; A[4] * A[4]
+ mov rdx, QWORD PTR [rax+32]
+ mulx r9, r8, rdx
+ adox rsi, rsi
+ adcx rsi, r8
+ adox rbx, rbx
+ adcx rbx, r9
+ ; A[5] * A[5]
+ mov rdx, QWORD PTR [rax+40]
+ mulx r9, r8, rdx
+ adox rbp, rbp
+ adcx rbp, r8
+ adcx r9, rcx
+ mov r8, 0
+ adox r9, r8
+ pop rcx
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov QWORD PTR [rcx+32], r13
+ mov QWORD PTR [rcx+40], r14
+ mov QWORD PTR [rcx+48], r15
+ mov QWORD PTR [rcx+56], rdi
+ mov QWORD PTR [rcx+64], rsi
+ mov QWORD PTR [rcx+72], rbx
+ mov QWORD PTR [rcx+80], rbp
+ mov QWORD PTR [rcx+88], r9
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_sqr_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_384_cond_sub_avx2_6 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov QWORD PTR [rcx+40], r12
+ sbb rax, 0
+ pop r12
+ ret
+sp_384_cond_sub_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_384_div2_avx2_6 PROC
+ push r12
+ push r13
+ mov r13, QWORD PTR [rdx]
+ xor r12, r12
+ mov r10, r13
+ and r13, 1
+ neg r13
+ mov rax, QWORD PTR [r8]
+ mov r9, QWORD PTR [r8+8]
+ mov r10, QWORD PTR [rdx]
+ mov r11, QWORD PTR [rdx+8]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ add r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx], r10
+ mov QWORD PTR [rcx+8], r11
+ mov rax, QWORD PTR [r8+16]
+ mov r9, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [r8+32]
+ mov r9, QWORD PTR [r8+40]
+ mov r10, QWORD PTR [rdx+32]
+ mov r11, QWORD PTR [rdx+40]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+32], r10
+ mov QWORD PTR [rcx+40], r11
+ adc r12, 0
+ mov r10, QWORD PTR [rcx]
+ mov r11, QWORD PTR [rcx+8]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rcx+16]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rcx+24]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rcx+32]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rcx+40]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+32], r10
+ shrd r11, r12, 1
+ mov QWORD PTR [rcx+40], r11
+ pop r13
+ pop r12
+ ret
+sp_384_div2_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_entry_64_6 PROC
+ mov rax, 1
+ movd xmm13, r8d
+ add rdx, 96
+ movd xmm15, eax
+ mov rax, 63
+ pshufd xmm15, xmm15, 0
+ pshufd xmm13, xmm13, 0
+ pxor xmm14, xmm14
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ pxor xmm4, xmm4
+ pxor xmm5, xmm5
+ movdqa xmm14, xmm15
+L_384_get_entry_64_6_start:
+ movdqa xmm12, xmm14
+ paddd xmm14, xmm15
+ pcmpeqd xmm12, xmm13
+ movdqa xmm6, [rdx]
+ movdqa xmm7, [rdx+16]
+ movdqa xmm8, [rdx+32]
+ movdqa xmm9, [rdx+48]
+ movdqa xmm10, [rdx+64]
+ movdqa xmm11, [rdx+80]
+ add rdx, 96
+ pand xmm6, xmm12
+ pand xmm7, xmm12
+ pand xmm8, xmm12
+ pand xmm9, xmm12
+ pand xmm10, xmm12
+ pand xmm11, xmm12
+ por xmm0, xmm6
+ por xmm1, xmm7
+ por xmm2, xmm8
+ por xmm3, xmm9
+ por xmm4, xmm10
+ por xmm5, xmm11
+ dec rax
+ jnz L_384_get_entry_64_6_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+32], xmm2
+ movdqu [rcx+96], xmm3
+ movdqu [rcx+112], xmm4
+ movdqu [rcx+128], xmm5
+ ret
+sp_384_get_entry_64_6 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_entry_64_avx2_6 PROC
+ mov rax, 1
+ movd xmm9, r8d
+ add rdx, 96
+ movd xmm11, eax
+ mov rax, 64
+ vpxor ymm10, ymm10, ymm10
+ vpermd ymm9, ymm10, ymm9
+ vpermd ymm11, ymm10, ymm11
+ vpxor ymm0, ymm0, ymm0
+ vpxor xmm1, xmm1, xmm1
+ vpxor ymm2, ymm2, ymm2
+ vpxor xmm3, xmm3, xmm3
+ vmovdqa ymm10, ymm11
+L_384_get_entry_64_avx2_6_start:
+ vpcmpeqd ymm8, ymm10, ymm9
+ vpaddd ymm10, ymm10, ymm11
+ vmovupd ymm4, [rdx]
+ vmovdqu xmm5, OWORD PTR [rdx+32]
+ vmovupd ymm6, [rdx+48]
+ vmovdqu xmm7, OWORD PTR [rdx+80]
+ add rdx, 96
+ vpand ymm4, ymm4, ymm8
+ vpand xmm5, xmm5, xmm8
+ vpand ymm6, ymm6, ymm8
+ vpand xmm7, xmm7, xmm8
+ vpor ymm0, ymm0, ymm4
+ vpor xmm1, xmm1, xmm5
+ vpor ymm2, ymm2, ymm6
+ vpor xmm3, xmm3, xmm7
+ dec rax
+ jnz L_384_get_entry_64_avx2_6_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovdqu [rcx+32], xmm1
+ vmovupd YMMWORD PTR [rcx+96], ymm2
+ vmovdqu [rcx+128], xmm3
+ ret
+sp_384_get_entry_64_avx2_6 ENDP
+_text ENDS
+ENDIF
+ENDIF
+IFNDEF WC_NO_CACHE_RESISTANT
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_entry_65_6 PROC
+ mov rax, 1
+ movd xmm13, r8d
+ add rdx, 96
+ movd xmm15, eax
+ mov rax, 64
+ pshufd xmm15, xmm15, 0
+ pshufd xmm13, xmm13, 0
+ pxor xmm14, xmm14
+ pxor xmm0, xmm0
+ pxor xmm1, xmm1
+ pxor xmm2, xmm2
+ pxor xmm3, xmm3
+ pxor xmm4, xmm4
+ pxor xmm5, xmm5
+ movdqa xmm14, xmm15
+L_384_get_entry_65_6_start:
+ movdqa xmm12, xmm14
+ paddd xmm14, xmm15
+ pcmpeqd xmm12, xmm13
+ movdqa xmm6, [rdx]
+ movdqa xmm7, [rdx+16]
+ movdqa xmm8, [rdx+32]
+ movdqa xmm9, [rdx+48]
+ movdqa xmm10, [rdx+64]
+ movdqa xmm11, [rdx+80]
+ add rdx, 96
+ pand xmm6, xmm12
+ pand xmm7, xmm12
+ pand xmm8, xmm12
+ pand xmm9, xmm12
+ pand xmm10, xmm12
+ pand xmm11, xmm12
+ por xmm0, xmm6
+ por xmm1, xmm7
+ por xmm2, xmm8
+ por xmm3, xmm9
+ por xmm4, xmm10
+ por xmm5, xmm11
+ dec rax
+ jnz L_384_get_entry_65_6_start
+ movdqu [rcx], xmm0
+ movdqu [rcx+16], xmm1
+ movdqu [rcx+32], xmm2
+ movdqu [rcx+96], xmm3
+ movdqu [rcx+112], xmm4
+ movdqu [rcx+128], xmm5
+ ret
+sp_384_get_entry_65_6 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Touch each possible entry that could be being copied.
+; *
+; * r Point to copy into.
+; * table Table - start of the entires to access
+; * idx Index of entry to retrieve.
+; */
+_text SEGMENT READONLY PARA
+sp_384_get_entry_65_avx2_6 PROC
+ mov rax, 1
+ movd xmm9, r8d
+ add rdx, 96
+ movd xmm11, eax
+ mov rax, 65
+ vpxor ymm10, ymm10, ymm10
+ vpermd ymm9, ymm10, ymm9
+ vpermd ymm11, ymm10, ymm11
+ vpxor ymm0, ymm0, ymm0
+ vpxor xmm1, xmm1, xmm1
+ vpxor ymm2, ymm2, ymm2
+ vpxor xmm3, xmm3, xmm3
+ vmovdqa ymm10, ymm11
+L_384_get_entry_65_avx2_6_start:
+ vpcmpeqd ymm8, ymm10, ymm9
+ vpaddd ymm10, ymm10, ymm11
+ vmovupd ymm4, [rdx]
+ vmovdqu xmm5, OWORD PTR [rdx+32]
+ vmovupd ymm6, [rdx+48]
+ vmovdqu xmm7, OWORD PTR [rdx+80]
+ add rdx, 96
+ vpand ymm4, ymm4, ymm8
+ vpand xmm5, xmm5, xmm8
+ vpand ymm6, ymm6, ymm8
+ vpand xmm7, xmm7, xmm8
+ vpor ymm0, ymm0, ymm4
+ vpor xmm1, xmm1, xmm5
+ vpor ymm2, ymm2, ymm6
+ vpor xmm3, xmm3, xmm7
+ dec rax
+ jnz L_384_get_entry_65_avx2_6_start
+ vmovupd YMMWORD PTR [rcx], ymm0
+ vmovdqu [rcx+32], xmm1
+ vmovupd YMMWORD PTR [rcx+96], ymm2
+ vmovdqu [rcx+128], xmm3
+ ret
+sp_384_get_entry_65_avx2_6 ENDP
+_text ENDS
+ENDIF
+ENDIF
+; /* Add 1 to a. (a = a + 1)
+; *
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_add_one_6 PROC
+ add QWORD PTR [rcx], 1
+ adc QWORD PTR [rcx+8], 0
+ adc QWORD PTR [rcx+16], 0
+ adc QWORD PTR [rcx+24], 0
+ adc QWORD PTR [rcx+32], 0
+ adc QWORD PTR [rcx+40], 0
+ ret
+sp_384_add_one_6 ENDP
+_text ENDS
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_384_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 48
+ xor r13, r13
+ jmp L_384_from_bin_bswap_64_end
+L_384_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_384_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_384_from_bin_bswap_64_start
+ jmp L_384_from_bin_bswap_8_end
+L_384_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_384_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_384_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_384_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_384_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_384_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_384_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_384_from_bin_bswap_zero_end
+L_384_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_384_from_bin_bswap_zero_start
+L_384_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_384_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_384_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 48
+ xor r13, r13
+ jmp L_384_from_bin_movbe_64_end
+L_384_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_384_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_384_from_bin_movbe_64_start
+ jmp L_384_from_bin_movbe_8_end
+L_384_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_384_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_384_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_384_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_384_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_384_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_384_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_384_from_bin_movbe_zero_end
+L_384_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_384_from_bin_movbe_zero_start
+L_384_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_384_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 48
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_384_to_bin_bswap PROC
+ mov rax, QWORD PTR [rcx+40]
+ mov r8, QWORD PTR [rcx+32]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ mov rax, QWORD PTR [rcx+24]
+ mov r8, QWORD PTR [rcx+16]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ mov rax, QWORD PTR [rcx+8]
+ mov r8, QWORD PTR [rcx]
+ bswap rax
+ bswap r8
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ ret
+sp_384_to_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Write r as big endian to byte array.
+; * Fixed length number of bytes written: 48
+; * Uses the movbe instruction which is optional.
+; *
+; * r A single precision integer.
+; * a Byte array.
+; */
+_text SEGMENT READONLY PARA
+sp_384_to_bin_movbe PROC
+ movbe rax, QWORD PTR [rcx+40]
+ movbe r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rdx], rax
+ mov QWORD PTR [rdx+8], r8
+ movbe rax, QWORD PTR [rcx+24]
+ movbe r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rdx+16], rax
+ mov QWORD PTR [rdx+24], r8
+ movbe rax, QWORD PTR [rcx+8]
+ movbe r8, QWORD PTR [rcx]
+ mov QWORD PTR [rdx+32], rax
+ mov QWORD PTR [rdx+40], r8
+ ret
+sp_384_to_bin_movbe ENDP
+_text ENDS
+ENDIF
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_384_sub_in_place_6 PROC
+ xor rax, rax
+ mov r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ mov r12, QWORD PTR [rdx+32]
+ mov r13, QWORD PTR [rdx+40]
+ sub QWORD PTR [rcx], r8
+ sbb QWORD PTR [rcx+8], r9
+ sbb QWORD PTR [rcx+16], r10
+ sbb QWORD PTR [rcx+24], r11
+ sbb QWORD PTR [rcx+32], r12
+ sbb QWORD PTR [rcx+40], r13
+ sbb rax, 0
+ pop r13
+ pop r12
+ ret
+sp_384_sub_in_place_6 ENDP
+_text ENDS
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mul_d_6 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+40], r12
+ mov QWORD PTR [rcx+48], r10
+ pop r12
+ ret
+sp_384_mul_d_6 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_384_mul_d_avx2_6 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+40], r12
+ mov QWORD PTR [rcx+48], r11
+ pop r13
+ pop r12
+ ret
+sp_384_mul_d_avx2_6 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_384_word_asm_6 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_384_word_asm_6 ENDP
+_text ENDS
+ENDIF
+; /* Shift number right by 1 bit. (r = a >> 1)
+; *
+; * r Result of right shift by 1.
+; * a Number to shift.
+; */
+_text SEGMENT READONLY PARA
+sp_384_rshift1_6 PROC
+ push r12
+ mov rax, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rdx+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov r11, QWORD PTR [rdx+32]
+ mov r12, QWORD PTR [rdx+40]
+ shrd rax, r8, 1
+ shrd r8, r9, 1
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shrd r11, r12, 1
+ shr r12, 1
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r8
+ mov QWORD PTR [rcx+16], r9
+ mov QWORD PTR [rcx+24], r10
+ mov QWORD PTR [rcx+32], r11
+ mov QWORD PTR [rcx+40], r12
+ pop r12
+ ret
+sp_384_rshift1_6 ENDP
+_text ENDS
+; /* Divide the number by 2 mod the prime. (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus
+; */
+_text SEGMENT READONLY PARA
+sp_384_div2_mod_6 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ mov r12, QWORD PTR [rdx+32]
+ mov r13, QWORD PTR [rdx+40]
+ mov r14, QWORD PTR [r8]
+ mov r15, QWORD PTR [r8+8]
+ mov rdi, QWORD PTR [r8+16]
+ mov rsi, QWORD PTR [r8+24]
+ mov rbx, QWORD PTR [r8+32]
+ mov rbp, QWORD PTR [r8+40]
+ mov r8, rax
+ and r8, 1
+ je L_384_mod_inv_6_div2_mod_no_add
+ add rax, r14
+ adc r9, r15
+ adc r10, rdi
+ adc r11, rsi
+ adc r12, rbx
+ adc r13, rbp
+ mov r8, 0
+ adc r8, 0
+L_384_mod_inv_6_div2_mod_no_add:
+ shrd rax, r9, 1
+ shrd r9, r10, 1
+ shrd r10, r11, 1
+ shrd r11, r12, 1
+ shrd r12, r13, 1
+ shrd r13, r8, 1
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov QWORD PTR [rcx+32], r12
+ mov QWORD PTR [rcx+40], r13
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_384_div2_mod_6 ENDP
+_text ENDS
+_text SEGMENT READONLY PARA
+sp_384_num_bits_6 PROC
+ xor rax, rax
+ mov rdx, QWORD PTR [rcx+40]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_320
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 321
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_320:
+ mov rdx, QWORD PTR [rcx+32]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_256
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 257
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_256:
+ mov rdx, QWORD PTR [rcx+24]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_192
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 193
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_192:
+ mov rdx, QWORD PTR [rcx+16]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_128
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 129
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_128:
+ mov rdx, QWORD PTR [rcx+8]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_64
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 65
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_64:
+ mov rdx, QWORD PTR [rcx]
+ cmp rdx, 0
+ je L_384_num_bits_6_end_0
+ mov rax, -1
+ bsr rax, rdx
+ add rax, 1
+ jmp L_384_num_bits_6_done
+L_384_num_bits_6_end_0:
+L_384_num_bits_6_done:
+ ret
+sp_384_num_bits_6 ENDP
+_text ENDS
+ENDIF
+IFDEF WOLFSSL_SP_1024
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mul_16 PROC
+ push r12
+ mov r9, rdx
+ sub rsp, 128
+ ; A[0] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ mov QWORD PTR [rsp], rax
+ mov r11, rdx
+ ; A[0] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+8], r11
+ ; A[0] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+16], r12
+ ; A[0] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+24], r10
+ ; A[0] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+32], r11
+ ; A[0] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+40], r12
+ ; A[0] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+48], r10
+ ; A[0] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+56], r11
+ ; A[0] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+64], r12
+ ; A[0] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+72], r10
+ ; A[0] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+80], r11
+ ; A[0] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+88], r12
+ ; A[0] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+96], r10
+ ; A[0] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[1] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+104], r11
+ ; A[0] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+8]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[2] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+112], r12
+ ; A[0] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[1] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+8]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[2] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+16]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[3] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[0]
+ mov rax, QWORD PTR [r8]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rsp+120], r10
+ ; A[1] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+8]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+16]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[3] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+24]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[4] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+128], r11
+ ; A[2] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+16]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+24]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[4] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+32]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[5] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+136], r12
+ ; A[3] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+24]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+32]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[5] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+40]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[6] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+144], r10
+ ; A[4] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+32]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+40]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[6] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+48]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[7] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+152], r11
+ ; A[5] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+40]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+48]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[7] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+56]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[8] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+160], r12
+ ; A[6] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+48]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+56]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[8] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+64]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[9] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+168], r10
+ ; A[7] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+56]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+64]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[9] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+72]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[10] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+176], r11
+ ; A[8] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+64]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+72]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[10] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+80]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[11] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+184], r12
+ ; A[9] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+72]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+80]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[11] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+88]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[12] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+192], r10
+ ; A[10] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+80]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+88]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[12] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+96]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[13] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+200], r11
+ ; A[11] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+88]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+96]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+104]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[14] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+208], r12
+ ; A[12] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+96]
+ xor r12, r12
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+104]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[14] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+112]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ ; A[15] * B[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ adc r12, 0
+ mov QWORD PTR [rcx+216], r10
+ ; A[13] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+104]
+ xor r10, r10
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+112]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ ; A[15] * B[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r9+120]
+ add r11, rax
+ adc r12, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+224], r11
+ ; A[14] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+112]
+ xor r11, r11
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r9+120]
+ add r12, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+232], r12
+ ; A[15] * B[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+240], r10
+ mov QWORD PTR [rcx+248], r11
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r10, QWORD PTR [rsp+16]
+ mov r11, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r10, QWORD PTR [rsp+48]
+ mov r11, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r10, QWORD PTR [rsp+80]
+ mov r11, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rsp+96]
+ mov rdx, QWORD PTR [rsp+104]
+ mov r10, QWORD PTR [rsp+112]
+ mov r11, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], rdx
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ add rsp, 128
+ pop r12
+ ret
+sp_1024_mul_16 ENDP
+_text ENDS
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_sqr_16 PROC
+ push r12
+ push r13
+ push r14
+ mov r8, rdx
+ sub rsp, 128
+ ; A[0] * A[0]
+ mov rax, QWORD PTR [r8]
+ mul rax
+ xor r11, r11
+ mov QWORD PTR [rsp], rax
+ mov r10, rdx
+ ; A[0] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+8], r10
+ ; A[0] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[1] * A[1]
+ mov rax, QWORD PTR [r8+8]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rsp+16], r11
+ ; A[0] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[1] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul QWORD PTR [r8+8]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rsp+24], r9
+ ; A[0] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[1] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+8]
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[2] * A[2]
+ mov rax, QWORD PTR [r8+16]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rsp+32], r10
+ ; A[0] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+40], r11
+ ; A[0] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[3]
+ mov rax, QWORD PTR [r8+24]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+48], r9
+ ; A[0] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+56], r10
+ ; A[0] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[4]
+ mov rax, QWORD PTR [r8+32]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+64], r11
+ ; A[0] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+72], r9
+ ; A[0] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[5]
+ mov rax, QWORD PTR [r8+40]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+80], r10
+ ; A[0] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+88], r11
+ ; A[0] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[6]
+ mov rax, QWORD PTR [r8+48]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+96], r9
+ ; A[0] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rsp+104], r10
+ ; A[0] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[7]
+ mov rax, QWORD PTR [r8+56]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rsp+112], r11
+ ; A[0] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[1] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+8]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[2] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rsp+120], r9
+ ; A[1] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+8]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[2] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+16]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[3] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[8]
+ mov rax, QWORD PTR [r8+64]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+128], r10
+ ; A[2] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+16]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[3] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+24]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[4] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+136], r11
+ ; A[3] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+24]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[4] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+32]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[5] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[9]
+ mov rax, QWORD PTR [r8+72]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+144], r9
+ ; A[4] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+32]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[5] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+40]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[6] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+152], r10
+ ; A[5] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+40]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[6] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+48]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[7] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[10]
+ mov rax, QWORD PTR [r8+80]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+160], r11
+ ; A[6] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+48]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[7] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+56]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[8] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+168], r9
+ ; A[7] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+56]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[8] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+64]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[9] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[11]
+ mov rax, QWORD PTR [r8+88]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+176], r10
+ ; A[8] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+64]
+ xor r10, r10
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[9] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+72]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[10] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r11, r12
+ adc r9, r13
+ adc r10, r14
+ mov QWORD PTR [rcx+184], r11
+ ; A[9] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+72]
+ xor r11, r11
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[10] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+80]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[11] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[12] * A[12]
+ mov rax, QWORD PTR [r8+96]
+ mul rax
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r9, r12
+ adc r10, r13
+ adc r11, r14
+ mov QWORD PTR [rcx+192], r9
+ ; A[10] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+80]
+ xor r9, r9
+ xor r14, r14
+ mov r12, rax
+ mov r13, rdx
+ ; A[11] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+88]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ ; A[12] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul QWORD PTR [r8+96]
+ add r12, rax
+ adc r13, rdx
+ adc r14, 0
+ add r12, r12
+ adc r13, r13
+ adc r14, r14
+ add r10, r12
+ adc r11, r13
+ adc r9, r14
+ mov QWORD PTR [rcx+200], r10
+ ; A[11] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+88]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[12] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+96]
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ ; A[13] * A[13]
+ mov rax, QWORD PTR [r8+104]
+ mul rax
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+208], r11
+ ; A[12] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+96]
+ xor r11, r11
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ ; A[13] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul QWORD PTR [r8+104]
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ add r9, rax
+ adc r10, rdx
+ adc r11, 0
+ mov QWORD PTR [rcx+216], r9
+ ; A[13] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+104]
+ xor r9, r9
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ ; A[14] * A[14]
+ mov rax, QWORD PTR [r8+112]
+ mul rax
+ add r10, rax
+ adc r11, rdx
+ adc r9, 0
+ mov QWORD PTR [rcx+224], r10
+ ; A[14] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul QWORD PTR [r8+112]
+ xor r10, r10
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ add r11, rax
+ adc r9, rdx
+ adc r10, 0
+ mov QWORD PTR [rcx+232], r11
+ ; A[15] * A[15]
+ mov rax, QWORD PTR [r8+120]
+ mul rax
+ add r9, rax
+ adc r10, rdx
+ mov QWORD PTR [rcx+240], r9
+ mov QWORD PTR [rcx+248], r10
+ mov rax, QWORD PTR [rsp]
+ mov rdx, QWORD PTR [rsp+8]
+ mov r12, QWORD PTR [rsp+16]
+ mov r13, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], rdx
+ mov QWORD PTR [rcx+16], r12
+ mov QWORD PTR [rcx+24], r13
+ mov rax, QWORD PTR [rsp+32]
+ mov rdx, QWORD PTR [rsp+40]
+ mov r12, QWORD PTR [rsp+48]
+ mov r13, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], rdx
+ mov QWORD PTR [rcx+48], r12
+ mov QWORD PTR [rcx+56], r13
+ mov rax, QWORD PTR [rsp+64]
+ mov rdx, QWORD PTR [rsp+72]
+ mov r12, QWORD PTR [rsp+80]
+ mov r13, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], rdx
+ mov QWORD PTR [rcx+80], r12
+ mov QWORD PTR [rcx+88], r13
+ mov rax, QWORD PTR [rsp+96]
+ mov rdx, QWORD PTR [rsp+104]
+ mov r12, QWORD PTR [rsp+112]
+ mov r13, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], rdx
+ mov QWORD PTR [rcx+112], r12
+ mov QWORD PTR [rcx+120], r13
+ add rsp, 128
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_1024_sqr_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Multiply a and b into r. (r = a * b)
+; *
+; * r Result of multiplication.
+; * a First number to multiply.
+; * b Second number to multiply.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mul_avx2_16 PROC
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ mov rbp, r8
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 128
+ cmp r9, r8
+ mov rbx, rsp
+ cmovne rbx, r8
+ cmp rbp, r8
+ cmove rbx, rsp
+ add r8, 128
+ xor rdi, rdi
+ mov rdx, QWORD PTR [r9]
+ ; A[0] * B[0]
+ mulx r11, r10, QWORD PTR [rbp]
+ ; A[0] * B[1]
+ mulx r12, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx], r10
+ adcx r11, rax
+ ; A[0] * B[2]
+ mulx r13, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+8], r11
+ adcx r12, rax
+ ; A[0] * B[3]
+ mulx r14, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ mov QWORD PTR [rbx+24], r13
+ ; A[0] * B[4]
+ mulx r10, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ ; A[0] * B[5]
+ mulx r11, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ ; A[0] * B[6]
+ mulx r12, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ ; A[0] * B[7]
+ mulx r13, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ mov QWORD PTR [rbx+56], r12
+ ; A[0] * B[8]
+ mulx r14, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ ; A[0] * B[9]
+ mulx r10, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ ; A[0] * B[10]
+ mulx r11, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ ; A[0] * B[11]
+ mulx r12, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ mov QWORD PTR [rbx+88], r11
+ ; A[0] * B[12]
+ mulx r13, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ ; A[0] * B[13]
+ mulx r14, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ ; A[0] * B[14]
+ mulx r10, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ ; A[0] * B[15]
+ mulx r11, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adcx r11, rdi
+ mov r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [rbx+120], r10
+ mov QWORD PTR [r8], r11
+ mov rdx, QWORD PTR [r9+8]
+ mov r11, QWORD PTR [rbx+8]
+ mov r12, QWORD PTR [rbx+16]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ ; A[1] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[1] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[1] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+32], r14
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ ; A[1] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[1] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+64], r13
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[1] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[1] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[1] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[1] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[1] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[1] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[1] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [rbx+120], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8], r11
+ mov QWORD PTR [r8+8], r12
+ mov rdx, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [rbx+16]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ ; A[2] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+16], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[2] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[2] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+40], r10
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ ; A[2] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[2] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+72], r14
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[2] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[2] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[2] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[2] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[2] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[2] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r13
+ mov rdx, QWORD PTR [r9+24]
+ mov r13, QWORD PTR [rbx+24]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ ; A[3] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+24], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[3] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+48], r11
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ ; A[3] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[3] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+80], r10
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[3] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[3] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[3] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[3] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[3] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+8], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+16], r13
+ mov QWORD PTR [r8+24], r14
+ mov rdx, QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rbx+32]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ ; A[4] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+32], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+56], r12
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ ; A[4] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+88], r11
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[4] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[4] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[4] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[4] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[4] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[4] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[4] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+16], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+24], r14
+ mov QWORD PTR [r8+32], r10
+ mov rdx, QWORD PTR [r9+40]
+ mov r10, QWORD PTR [rbx+40]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ ; A[5] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+40], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[5] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+64], r13
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[5] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[5] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[5] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[5] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[5] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[5] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[5] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[5] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+24], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+32], r10
+ mov QWORD PTR [r8+40], r11
+ mov rdx, QWORD PTR [r9+48]
+ mov r11, QWORD PTR [rbx+48]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ ; A[6] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+48], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[6] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[6] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+72], r14
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[6] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[6] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[6] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[6] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[6] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[6] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[6] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+32], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+40], r11
+ mov QWORD PTR [r8+48], r12
+ mov rdx, QWORD PTR [r9+56]
+ mov r12, QWORD PTR [rbx+56]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ ; A[7] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+56], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[7] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[7] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+80], r10
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[7] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[7] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[7] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[7] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[7] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[7] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[7] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+40], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+48], r12
+ mov QWORD PTR [r8+56], r13
+ mov rdx, QWORD PTR [r9+64]
+ mov r13, QWORD PTR [rbx+64]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ ; A[8] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+64], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[8] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbx+88], r11
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[8] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[8] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[8] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[8] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r14
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[8] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[8] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+48], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+56], r13
+ mov QWORD PTR [r8+64], r14
+ mov rdx, QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rbx+72]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ ; A[9] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+72], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [rbx+96], r12
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[9] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[9] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[9] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[9] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ ; A[9] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[9] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[9] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[9] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+56], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+64], r14
+ mov QWORD PTR [r8+72], r10
+ mov rdx, QWORD PTR [r9+80]
+ mov r10, QWORD PTR [rbx+80]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ ; A[10] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+80], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[10] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [rbx+104], r13
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[10] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[10] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[10] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[10] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r11
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[10] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[10] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[10] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[10] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+64], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+72], r10
+ mov QWORD PTR [r8+80], r11
+ mov rdx, QWORD PTR [r9+88]
+ mov r11, QWORD PTR [rbx+88]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ ; A[11] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+88], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[11] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[11] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [rbx+112], r14
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[11] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[11] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[11] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[11] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[11] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+48], r12
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ ; A[11] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[11] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[11] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+72], r10
+ mov r12, rdi
+ adcx r11, rax
+ adox r12, rcx
+ adcx r12, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+80], r11
+ mov QWORD PTR [r8+88], r12
+ mov rdx, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [rbx+96]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ ; A[12] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+96], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[12] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[12] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbx+120], r10
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ ; A[12] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[12] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r14
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ ; A[12] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[12] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+56], r13
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ ; A[12] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[12] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+80], r11
+ mov r13, rdi
+ adcx r12, rax
+ adox r13, rcx
+ adcx r13, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+88], r12
+ mov QWORD PTR [r8+96], r13
+ mov rdx, QWORD PTR [r9+104]
+ mov r13, QWORD PTR [rbx+104]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[13] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+104], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[13] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8], r11
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[13] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[13] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[13] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[13] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+64], r14
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ mov r13, QWORD PTR [r8+96]
+ ; A[13] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+80], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[13] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+88], r12
+ mov r14, rdi
+ adcx r13, rax
+ adox r14, rcx
+ adcx r14, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+96], r13
+ mov QWORD PTR [r8+104], r14
+ mov rdx, QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rbx+112]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ ; A[14] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+112], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+8], r12
+ mov r14, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ ; A[14] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+16], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r11
+ mov r13, QWORD PTR [r8+56]
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ ; A[14] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[14] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+48], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[14] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+72], r10
+ mov r12, QWORD PTR [r8+88]
+ mov r13, QWORD PTR [r8+96]
+ mov r14, QWORD PTR [r8+104]
+ ; A[14] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+80], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[14] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+88], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[14] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+96], r13
+ mov r10, rdi
+ adcx r14, rax
+ adox r10, rcx
+ adcx r10, r15
+ mov r15, rdi
+ adox r15, rdi
+ adcx r15, rdi
+ mov QWORD PTR [r8+104], r14
+ mov QWORD PTR [r8+112], r10
+ mov rdx, QWORD PTR [r9+120]
+ mov r10, QWORD PTR [rbx+120]
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ mov r13, QWORD PTR [r8+16]
+ mov r14, QWORD PTR [r8+24]
+ ; A[15] * B[0]
+ mulx rcx, rax, QWORD PTR [rbp]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[1]
+ mulx rcx, rax, QWORD PTR [rbp+8]
+ mov QWORD PTR [rbx+120], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] * B[2]
+ mulx rcx, rax, QWORD PTR [rbp+16]
+ mov QWORD PTR [r8], r11
+ adcx r12, rax
+ adox r13, rcx
+ ; A[15] * B[3]
+ mulx rcx, rax, QWORD PTR [rbp+24]
+ mov QWORD PTR [r8+8], r12
+ adcx r13, rax
+ adox r14, rcx
+ mov QWORD PTR [r8+16], r13
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [r8+48]
+ mov r13, QWORD PTR [r8+56]
+ ; A[15] * B[4]
+ mulx rcx, rax, QWORD PTR [rbp+32]
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[5]
+ mulx rcx, rax, QWORD PTR [rbp+40]
+ mov QWORD PTR [r8+24], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[6]
+ mulx rcx, rax, QWORD PTR [rbp+48]
+ mov QWORD PTR [r8+32], r10
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] * B[7]
+ mulx rcx, rax, QWORD PTR [rbp+56]
+ mov QWORD PTR [r8+40], r11
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r8+48], r12
+ mov r14, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ mov r11, QWORD PTR [r8+80]
+ mov r12, QWORD PTR [r8+88]
+ ; A[15] * B[8]
+ mulx rcx, rax, QWORD PTR [rbp+64]
+ adcx r13, rax
+ adox r14, rcx
+ ; A[15] * B[9]
+ mulx rcx, rax, QWORD PTR [rbp+72]
+ mov QWORD PTR [r8+56], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[10]
+ mulx rcx, rax, QWORD PTR [rbp+80]
+ mov QWORD PTR [r8+64], r14
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] * B[11]
+ mulx rcx, rax, QWORD PTR [rbp+88]
+ mov QWORD PTR [r8+72], r10
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+80], r11
+ mov r13, QWORD PTR [r8+96]
+ mov r14, QWORD PTR [r8+104]
+ mov r10, QWORD PTR [r8+112]
+ ; A[15] * B[12]
+ mulx rcx, rax, QWORD PTR [rbp+96]
+ adcx r12, rax
+ adox r13, rcx
+ ; A[15] * B[13]
+ mulx rcx, rax, QWORD PTR [rbp+104]
+ mov QWORD PTR [r8+88], r12
+ adcx r13, rax
+ adox r14, rcx
+ ; A[15] * B[14]
+ mulx rcx, rax, QWORD PTR [rbp+112]
+ mov QWORD PTR [r8+96], r13
+ adcx r14, rax
+ adox r10, rcx
+ ; A[15] * B[15]
+ mulx rcx, rax, QWORD PTR [rbp+120]
+ mov QWORD PTR [r8+104], r14
+ mov r11, rdi
+ adcx r10, rax
+ adox r11, rcx
+ adcx r11, r15
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r11
+ sub r8, 128
+ cmp r9, r8
+ je L_start_1024_mul_avx2_16
+ cmp rbp, r8
+ jne L_end_1024_mul_avx2_16
+L_start_1024_mul_avx2_16:
+ vmovdqu xmm0, OWORD PTR [rbx]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+48]
+ vmovups OWORD PTR [r8+48], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+64]
+ vmovups OWORD PTR [r8+64], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+80]
+ vmovups OWORD PTR [r8+80], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+96]
+ vmovups OWORD PTR [r8+96], xmm0
+ vmovdqu xmm0, OWORD PTR [rbx+112]
+ vmovups OWORD PTR [r8+112], xmm0
+L_end_1024_mul_avx2_16:
+ add rsp, 128
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ pop rbx
+ ret
+sp_1024_mul_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Square a and put result in r. (r = a * a)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_sqr_avx2_16 PROC
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ mov r8, rcx
+ mov r9, rdx
+ sub rsp, 128
+ cmp r9, r8
+ mov rbp, rsp
+ cmovne rbp, r8
+ add r8, 128
+ xor r13, r13
+ ; Diagonal 1
+ xor r12, r12
+ ; A[1] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx r11, r10, QWORD PTR [r9+8]
+ ; A[2] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+8], r10
+ mov QWORD PTR [rbp+16], r11
+ mov r10, r13
+ mov r11, r13
+ ; A[3] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[4] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+24], r12
+ mov QWORD PTR [rbp+32], r10
+ mov r12, r13
+ mov r10, r13
+ ; A[5] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[6] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+40], r11
+ mov QWORD PTR [rbp+48], r12
+ mov r11, r13
+ mov r12, r13
+ ; A[7] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[8] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+56], r10
+ mov QWORD PTR [rbp+64], r11
+ mov r10, r13
+ mov r11, r13
+ ; A[9] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[10] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+72], r12
+ mov QWORD PTR [rbp+80], r10
+ mov r12, r13
+ mov r10, r13
+ ; A[11] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+88], r11
+ mov r15, r12
+ mov r11, r13
+ mov r12, r13
+ ; A[13] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r11, rax
+ adox r12, rcx
+ mov rdi, r10
+ mov rsi, r11
+ mov r10, r13
+ ; A[15] x A[0]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r10, rcx
+ mov rbx, r12
+ ; Carry
+ adcx r10, r13
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8], r10
+ ; Diagonal 2
+ mov r10, QWORD PTR [rbp+24]
+ mov r11, QWORD PTR [rbp+32]
+ mov r12, QWORD PTR [rbp+40]
+ ; A[2] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, QWORD PTR [r9+16]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[3] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+24], r10
+ mov QWORD PTR [rbp+32], r11
+ mov r10, QWORD PTR [rbp+48]
+ mov r11, QWORD PTR [rbp+56]
+ ; A[4] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[5] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+40], r12
+ mov QWORD PTR [rbp+48], r10
+ mov r12, QWORD PTR [rbp+64]
+ mov r10, QWORD PTR [rbp+72]
+ ; A[6] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[7] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+56], r11
+ mov QWORD PTR [rbp+64], r12
+ mov r11, QWORD PTR [rbp+80]
+ mov r12, QWORD PTR [rbp+88]
+ ; A[8] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[9] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+72], r10
+ mov QWORD PTR [rbp+80], r11
+ ; No load %r13 - %r8
+ ; No load %r14 - %r9
+ ; A[10] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r12, rax
+ adox r15, rcx
+ ; A[11] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r12
+ ; No store %r13
+ ; No load %r15 - %r10
+ ; No load %rbx - %r8
+ ; A[12] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[13] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ mov r12, r13
+ ; A[14] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[15] x A[1]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, r13
+ ; A[15] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, QWORD PTR [r9+120]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+16], r10
+ ; Diagonal 3
+ mov r10, QWORD PTR [rbp+40]
+ mov r11, QWORD PTR [rbp+48]
+ mov r12, QWORD PTR [rbp+56]
+ ; A[3] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[4] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+40], r10
+ mov QWORD PTR [rbp+48], r11
+ mov r10, QWORD PTR [rbp+64]
+ mov r11, QWORD PTR [rbp+72]
+ ; A[5] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[6] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+56], r12
+ mov QWORD PTR [rbp+64], r10
+ mov r12, QWORD PTR [rbp+80]
+ mov r10, QWORD PTR [rbp+88]
+ ; A[7] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[8] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [rbp+72], r11
+ mov QWORD PTR [rbp+80], r12
+ ; No load %r13 - %r9
+ ; No load %r14 - %r10
+ ; A[9] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r15, rcx
+ ; A[10] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r10
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; No load %rbx - %r9
+ ; A[11] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[12] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ ; A[13] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx rbx, rax
+ adox r12, rcx
+ ; A[14] x A[2]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r12, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r12
+ mov r11, QWORD PTR [r8+16]
+ mov r12, r13
+ ; A[14] x A[3]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r10
+ mov QWORD PTR [r8+16], r11
+ mov r10, r13
+ ; A[14] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+32], r10
+ ; Diagonal 4
+ mov r10, QWORD PTR [rbp+56]
+ mov r11, QWORD PTR [rbp+64]
+ mov r12, QWORD PTR [rbp+72]
+ ; A[4] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[5] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+56], r10
+ mov QWORD PTR [rbp+64], r11
+ mov r10, QWORD PTR [rbp+80]
+ mov r11, QWORD PTR [rbp+88]
+ ; A[6] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[7] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [rbp+72], r12
+ mov QWORD PTR [rbp+80], r10
+ ; No load %r13 - %r10
+ ; No load %r14 - %r8
+ ; A[8] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r11, rax
+ adox r15, rcx
+ ; A[9] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r11
+ ; No store %r13
+ ; No load %r15 - %r9
+ ; No load %rbx - %r10
+ ; A[10] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[11] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[12] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx rbx, rax
+ adox r10, rcx
+ ; A[13] x A[3]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r10, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[13] x A[4]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, r13
+ ; A[13] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+24], r10
+ mov QWORD PTR [r8+32], r11
+ mov r10, r13
+ ; A[13] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+48], r10
+ ; Diagonal 5
+ mov r10, QWORD PTR [rbp+72]
+ mov r11, QWORD PTR [rbp+80]
+ mov r12, QWORD PTR [rbp+88]
+ ; A[5] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[6] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [rbp+72], r10
+ mov QWORD PTR [rbp+80], r11
+ ; No load %r13 - %r8
+ ; No load %r14 - %r9
+ ; A[7] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r15, rcx
+ ; A[8] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r12
+ ; No store %r13
+ ; No load %r15 - %r10
+ ; No load %rbx - %r8
+ ; A[9] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[10] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[11] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[12] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[12] x A[5]
+ mov rdx, QWORD PTR [r9+96]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[12] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r10
+ mov r12, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [r8+40]
+ ; A[12] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[12] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov QWORD PTR [r8+32], r12
+ mov r11, QWORD PTR [r8+48]
+ mov r12, r13
+ ; A[12] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[12] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r10
+ mov QWORD PTR [r8+48], r11
+ mov r10, r13
+ ; A[12] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+56], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+64], r10
+ ; Diagonal 6
+ mov r10, QWORD PTR [rbp+88]
+ ; No load %r13 - %r9
+ ; No load %r14 - %r10
+ ; A[6] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r15, rcx
+ ; A[7] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r15, rax
+ adox rdi, rcx
+ mov QWORD PTR [rbp+88], r10
+ ; No store %r13
+ ; No load %r15 - %r8
+ ; No load %rbx - %r9
+ ; A[8] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[9] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [r8+8]
+ ; A[10] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx rbx, rax
+ adox r12, rcx
+ ; A[11] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r12
+ mov r11, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [r8+24]
+ ; A[11] x A[6]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[11] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+8], r10
+ mov QWORD PTR [r8+16], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[11] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[11] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+24], r12
+ mov QWORD PTR [r8+32], r10
+ mov r12, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [r8+56]
+ ; A[11] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[13] x A[9]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+40], r11
+ mov QWORD PTR [r8+48], r12
+ mov r11, QWORD PTR [r8+64]
+ mov r12, r13
+ ; A[13] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[13] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+56], r10
+ mov QWORD PTR [r8+64], r11
+ mov r10, r13
+ ; A[13] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+72], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+80], r10
+ ; Diagonal 7
+ ; No load %r14 - %r8
+ ; No load %r15 - %r9
+ ; No load %rbx - %r10
+ ; A[7] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx rdi, rax
+ adox rsi, rcx
+ ; A[8] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; No store %r14
+ ; No store %r15
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[9] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx rbx, rax
+ adox r10, rcx
+ ; A[10] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r10, rax
+ adox r11, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r10
+ mov r12, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [r8+24]
+ ; A[10] x A[7]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[10] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+8], r11
+ mov QWORD PTR [r8+16], r12
+ mov r11, QWORD PTR [r8+32]
+ mov r12, QWORD PTR [r8+40]
+ ; A[10] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[6]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+24], r10
+ mov QWORD PTR [r8+32], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[14] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[14] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+40], r12
+ mov QWORD PTR [r8+48], r10
+ mov r12, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [r8+72]
+ ; A[14] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[14] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+56], r11
+ mov QWORD PTR [r8+64], r12
+ mov r11, QWORD PTR [r8+80]
+ mov r12, r13
+ ; A[14] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[14] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+72], r10
+ mov QWORD PTR [r8+80], r11
+ mov r10, r13
+ ; A[14] x A[13]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+88], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+96], r10
+ ; Diagonal 8
+ ; No load %rbx - %r8
+ mov r11, QWORD PTR [r8]
+ mov r12, QWORD PTR [r8+8]
+ ; A[8] x A[7]
+ mov rdx, QWORD PTR [r9+56]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx rbx, rax
+ adox r11, rcx
+ ; A[9] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r11, rax
+ adox r12, rcx
+ ; No store %rbx
+ mov QWORD PTR [r8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[9] x A[8]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[15] x A[3]
+ mov rdx, QWORD PTR [r9+120]
+ mulx rcx, rax, QWORD PTR [r9+24]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+8], r12
+ mov QWORD PTR [r8+16], r10
+ mov r12, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [r8+40]
+ ; A[15] x A[4]
+ mulx rcx, rax, QWORD PTR [r9+32]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] x A[5]
+ mulx rcx, rax, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+24], r11
+ mov QWORD PTR [r8+32], r12
+ mov r11, QWORD PTR [r8+48]
+ mov r12, QWORD PTR [r8+56]
+ ; A[15] x A[6]
+ mulx rcx, rax, QWORD PTR [r9+48]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] x A[7]
+ mulx rcx, rax, QWORD PTR [r9+56]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+40], r10
+ mov QWORD PTR [r8+48], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ ; A[15] x A[8]
+ mulx rcx, rax, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r10, rcx
+ ; A[15] x A[9]
+ mulx rcx, rax, QWORD PTR [r9+72]
+ adcx r10, rax
+ adox r11, rcx
+ mov QWORD PTR [r8+56], r12
+ mov QWORD PTR [r8+64], r10
+ mov r12, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [r8+88]
+ ; A[15] x A[10]
+ mulx rcx, rax, QWORD PTR [r9+80]
+ adcx r11, rax
+ adox r12, rcx
+ ; A[15] x A[11]
+ mulx rcx, rax, QWORD PTR [r9+88]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+72], r11
+ mov QWORD PTR [r8+80], r12
+ mov r11, QWORD PTR [r8+96]
+ mov r12, r13
+ ; A[15] x A[12]
+ mulx rcx, rax, QWORD PTR [r9+96]
+ adcx r10, rax
+ adox r11, rcx
+ ; A[15] x A[13]
+ mulx rcx, rax, QWORD PTR [r9+104]
+ adcx r11, rax
+ adox r12, rcx
+ mov QWORD PTR [r8+88], r10
+ mov QWORD PTR [r8+96], r11
+ mov r10, r13
+ ; A[15] x A[14]
+ mulx rcx, rax, QWORD PTR [r9+112]
+ adcx r12, rax
+ adox r10, rcx
+ mov QWORD PTR [r8+104], r12
+ ; Carry
+ adcx r10, r14
+ mov r14, r13
+ adcx r14, r13
+ adox r14, r13
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r14
+ ; Double and Add in A[i] x A[i]
+ mov r11, QWORD PTR [rbp+8]
+ ; A[0] x A[0]
+ mov rdx, QWORD PTR [r9]
+ mulx rcx, rax, rdx
+ mov QWORD PTR [rbp], rax
+ adox r11, r11
+ adcx r11, rcx
+ mov QWORD PTR [rbp+8], r11
+ mov r10, QWORD PTR [rbp+16]
+ mov r11, QWORD PTR [rbp+24]
+ ; A[1] x A[1]
+ mov rdx, QWORD PTR [r9+8]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+16], r10
+ mov QWORD PTR [rbp+24], r11
+ mov r10, QWORD PTR [rbp+32]
+ mov r11, QWORD PTR [rbp+40]
+ ; A[2] x A[2]
+ mov rdx, QWORD PTR [r9+16]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+32], r10
+ mov QWORD PTR [rbp+40], r11
+ mov r10, QWORD PTR [rbp+48]
+ mov r11, QWORD PTR [rbp+56]
+ ; A[3] x A[3]
+ mov rdx, QWORD PTR [r9+24]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+48], r10
+ mov QWORD PTR [rbp+56], r11
+ mov r10, QWORD PTR [rbp+64]
+ mov r11, QWORD PTR [rbp+72]
+ ; A[4] x A[4]
+ mov rdx, QWORD PTR [r9+32]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+64], r10
+ mov QWORD PTR [rbp+72], r11
+ mov r10, QWORD PTR [rbp+80]
+ mov r11, QWORD PTR [rbp+88]
+ ; A[5] x A[5]
+ mov rdx, QWORD PTR [r9+40]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [rbp+80], r10
+ mov QWORD PTR [rbp+88], r11
+ ; A[6] x A[6]
+ mov rdx, QWORD PTR [r9+48]
+ mulx rcx, rax, rdx
+ adox r15, r15
+ adox rdi, rdi
+ adcx r15, rax
+ adcx rdi, rcx
+ ; A[7] x A[7]
+ mov rdx, QWORD PTR [r9+56]
+ mulx rcx, rax, rdx
+ adox rsi, rsi
+ adox rbx, rbx
+ adcx rsi, rax
+ adcx rbx, rcx
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ ; A[8] x A[8]
+ mov rdx, QWORD PTR [r9+64]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8], r10
+ mov QWORD PTR [r8+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ ; A[9] x A[9]
+ mov rdx, QWORD PTR [r9+72]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+16], r10
+ mov QWORD PTR [r8+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ ; A[10] x A[10]
+ mov rdx, QWORD PTR [r9+80]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+32], r10
+ mov QWORD PTR [r8+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ ; A[11] x A[11]
+ mov rdx, QWORD PTR [r9+88]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+48], r10
+ mov QWORD PTR [r8+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ ; A[12] x A[12]
+ mov rdx, QWORD PTR [r9+96]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+64], r10
+ mov QWORD PTR [r8+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ ; A[13] x A[13]
+ mov rdx, QWORD PTR [r9+104]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+80], r10
+ mov QWORD PTR [r8+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ ; A[14] x A[14]
+ mov rdx, QWORD PTR [r9+112]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+96], r10
+ mov QWORD PTR [r8+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ ; A[15] x A[15]
+ mov rdx, QWORD PTR [r9+120]
+ mulx rcx, rax, rdx
+ adox r10, r10
+ adox r11, r11
+ adcx r10, rax
+ adcx r11, rcx
+ mov QWORD PTR [r8+112], r10
+ mov QWORD PTR [r8+120], r11
+ mov QWORD PTR [r8+-32], r15
+ mov QWORD PTR [r8+-24], rdi
+ mov QWORD PTR [r8+-16], rsi
+ mov QWORD PTR [r8+-8], rbx
+ sub r8, 128
+ cmp r9, r8
+ jne L_end_1024_sqr_avx2_16
+ vmovdqu xmm0, OWORD PTR [rbp]
+ vmovups OWORD PTR [r8], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+16]
+ vmovups OWORD PTR [r8+16], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+32]
+ vmovups OWORD PTR [r8+32], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+48]
+ vmovups OWORD PTR [r8+48], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+64]
+ vmovups OWORD PTR [r8+64], xmm0
+ vmovdqu xmm0, OWORD PTR [rbp+80]
+ vmovups OWORD PTR [r8+80], xmm0
+L_end_1024_sqr_avx2_16:
+ add rsp, 128
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ ret
+sp_1024_sqr_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Add b to a into r. (r = a + b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_add_16 PROC
+ ; Add
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ add r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ adc r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ adc r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ adc r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ adc r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ adc r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ adc r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ adc r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ adc r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ adc r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ adc r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ adc r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ adc r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ adc r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ adc r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ adc r10, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+120], r10
+ adc rax, 0
+ ret
+sp_1024_add_16 ENDP
+_text ENDS
+; /* Sub b from a into a. (a -= b)
+; *
+; * a A single precision integer and result.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_sub_in_place_16 PROC
+ mov r8, QWORD PTR [rcx]
+ xor rax, rax
+ sub r8, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rcx+8]
+ mov QWORD PTR [rcx], r8
+ sbb r9, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rcx+16]
+ mov QWORD PTR [rcx+8], r9
+ sbb r8, QWORD PTR [rdx+16]
+ mov r9, QWORD PTR [rcx+24]
+ mov QWORD PTR [rcx+16], r8
+ sbb r9, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rcx+32]
+ mov QWORD PTR [rcx+24], r9
+ sbb r8, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov QWORD PTR [rcx+32], r8
+ sbb r9, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rcx+48]
+ mov QWORD PTR [rcx+40], r9
+ sbb r8, QWORD PTR [rdx+48]
+ mov r9, QWORD PTR [rcx+56]
+ mov QWORD PTR [rcx+48], r8
+ sbb r9, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rcx+64]
+ mov QWORD PTR [rcx+56], r9
+ sbb r8, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov QWORD PTR [rcx+64], r8
+ sbb r9, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rcx+80]
+ mov QWORD PTR [rcx+72], r9
+ sbb r8, QWORD PTR [rdx+80]
+ mov r9, QWORD PTR [rcx+88]
+ mov QWORD PTR [rcx+80], r8
+ sbb r9, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rcx+96]
+ mov QWORD PTR [rcx+88], r9
+ sbb r8, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov QWORD PTR [rcx+96], r8
+ sbb r9, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rcx+112]
+ mov QWORD PTR [rcx+104], r9
+ sbb r8, QWORD PTR [rdx+112]
+ mov r9, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx+112], r8
+ sbb r9, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+120], r9
+ sbb rax, 0
+ ret
+sp_1024_sub_in_place_16 ENDP
+_text ENDS
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_cond_sub_16 PROC
+ sub rsp, 128
+ mov rax, 0
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r9
+ and r11, r9
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov r10, QWORD PTR [rdx]
+ mov r8, QWORD PTR [rsp]
+ sub r10, r8
+ mov r11, QWORD PTR [rdx+8]
+ mov r8, QWORD PTR [rsp+8]
+ sbb r11, r8
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rdx+16]
+ mov r8, QWORD PTR [rsp+16]
+ sbb r10, r8
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rdx+24]
+ mov r8, QWORD PTR [rsp+24]
+ sbb r11, r8
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rdx+32]
+ mov r8, QWORD PTR [rsp+32]
+ sbb r10, r8
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rdx+40]
+ mov r8, QWORD PTR [rsp+40]
+ sbb r11, r8
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rdx+48]
+ mov r8, QWORD PTR [rsp+48]
+ sbb r10, r8
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rdx+56]
+ mov r8, QWORD PTR [rsp+56]
+ sbb r11, r8
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rdx+64]
+ mov r8, QWORD PTR [rsp+64]
+ sbb r10, r8
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rdx+72]
+ mov r8, QWORD PTR [rsp+72]
+ sbb r11, r8
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rdx+80]
+ mov r8, QWORD PTR [rsp+80]
+ sbb r10, r8
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rdx+88]
+ mov r8, QWORD PTR [rsp+88]
+ sbb r11, r8
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rdx+96]
+ mov r8, QWORD PTR [rsp+96]
+ sbb r10, r8
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rdx+104]
+ mov r8, QWORD PTR [rsp+104]
+ sbb r11, r8
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rdx+112]
+ mov r8, QWORD PTR [rsp+112]
+ sbb r10, r8
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rdx+120]
+ mov r8, QWORD PTR [rsp+120]
+ sbb r11, r8
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb rax, 0
+ add rsp, 128
+ ret
+sp_1024_cond_sub_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Conditionally subtract b from a using the mask m.
+; * m is -1 to subtract and 0 when not copying.
+; *
+; * r A single precision number representing condition subtract result.
+; * a A single precision number to subtract from.
+; * b A single precision number to subtract.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_cond_sub_avx2_16 PROC
+ push r12
+ mov rax, 0
+ mov r12, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx]
+ pext r12, r12, r9
+ sub r10, r12
+ mov r12, QWORD PTR [r8+8]
+ mov r11, QWORD PTR [rdx+8]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+16]
+ mov r12, QWORD PTR [rdx+16]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+8], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+24]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+16], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [rdx+32]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+24], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+40]
+ mov r12, QWORD PTR [rdx+40]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+32], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+48]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+40], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+56]
+ mov r11, QWORD PTR [rdx+56]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+48], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+64]
+ mov r12, QWORD PTR [rdx+64]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+56], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+72]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+64], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [rdx+80]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+72], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+88]
+ mov r12, QWORD PTR [rdx+88]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+80], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+96]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+88], r12
+ sbb r10, r11
+ mov r12, QWORD PTR [r8+104]
+ mov r11, QWORD PTR [rdx+104]
+ pext r12, r12, r9
+ mov QWORD PTR [rcx+96], r10
+ sbb r11, r12
+ mov r10, QWORD PTR [r8+112]
+ mov r12, QWORD PTR [rdx+112]
+ pext r10, r10, r9
+ mov QWORD PTR [rcx+104], r11
+ sbb r12, r10
+ mov r11, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+120]
+ pext r11, r11, r9
+ mov QWORD PTR [rcx+112], r12
+ sbb r10, r11
+ mov QWORD PTR [rcx+120], r10
+ sbb rax, 0
+ pop r12
+ ret
+sp_1024_cond_sub_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mul_d_16 PROC
+ push r12
+ mov r9, rdx
+ ; A[0] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9]
+ mov r10, rax
+ mov r11, rdx
+ mov QWORD PTR [rcx], r10
+ ; A[1] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+8]
+ add r11, rax
+ mov QWORD PTR [rcx+8], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[2] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+16]
+ add r12, rax
+ mov QWORD PTR [rcx+16], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[3] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+24]
+ add r10, rax
+ mov QWORD PTR [rcx+24], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[4] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+32]
+ add r11, rax
+ mov QWORD PTR [rcx+32], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[5] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ add r12, rax
+ mov QWORD PTR [rcx+40], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[6] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ add r10, rax
+ mov QWORD PTR [rcx+48], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[7] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+56]
+ add r11, rax
+ mov QWORD PTR [rcx+56], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[8] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+64]
+ add r12, rax
+ mov QWORD PTR [rcx+64], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[9] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+72]
+ add r10, rax
+ mov QWORD PTR [rcx+72], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[10] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+80]
+ add r11, rax
+ mov QWORD PTR [rcx+80], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[11] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ add r12, rax
+ mov QWORD PTR [rcx+88], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[12] * B
+ mov rax, r8
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ add r10, rax
+ mov QWORD PTR [rcx+96], r10
+ adc r11, rdx
+ adc r12, 0
+ ; A[13] * B
+ mov rax, r8
+ xor r10, r10
+ mul QWORD PTR [r9+104]
+ add r11, rax
+ mov QWORD PTR [rcx+104], r11
+ adc r12, rdx
+ adc r10, 0
+ ; A[14] * B
+ mov rax, r8
+ xor r11, r11
+ mul QWORD PTR [r9+112]
+ add r12, rax
+ mov QWORD PTR [rcx+112], r12
+ adc r10, rdx
+ adc r11, 0
+ ; A[15] * B
+ mov rax, r8
+ mul QWORD PTR [r9+120]
+ add r10, rax
+ adc r11, rdx
+ mov QWORD PTR [rcx+120], r10
+ mov QWORD PTR [rcx+128], r11
+ pop r12
+ ret
+sp_1024_mul_d_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Mul a by digit b into r. (r = a * b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision digit.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mul_d_avx2_16 PROC
+ push r12
+ push r13
+ mov rax, rdx
+ ; A[0] * B
+ mov rdx, r8
+ xor r13, r13
+ mulx r12, r11, QWORD PTR [rax]
+ mov QWORD PTR [rcx], r11
+ ; A[1] * B
+ mulx r10, r9, QWORD PTR [rax+8]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+8], r12
+ ; A[2] * B
+ mulx r10, r9, QWORD PTR [rax+16]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+16], r11
+ ; A[3] * B
+ mulx r10, r9, QWORD PTR [rax+24]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+24], r12
+ ; A[4] * B
+ mulx r10, r9, QWORD PTR [rax+32]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+32], r11
+ ; A[5] * B
+ mulx r10, r9, QWORD PTR [rax+40]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+40], r12
+ ; A[6] * B
+ mulx r10, r9, QWORD PTR [rax+48]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+48], r11
+ ; A[7] * B
+ mulx r10, r9, QWORD PTR [rax+56]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+56], r12
+ ; A[8] * B
+ mulx r10, r9, QWORD PTR [rax+64]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+64], r11
+ ; A[9] * B
+ mulx r10, r9, QWORD PTR [rax+72]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+72], r12
+ ; A[10] * B
+ mulx r10, r9, QWORD PTR [rax+80]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+80], r11
+ ; A[11] * B
+ mulx r10, r9, QWORD PTR [rax+88]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+88], r12
+ ; A[12] * B
+ mulx r10, r9, QWORD PTR [rax+96]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+96], r11
+ ; A[13] * B
+ mulx r10, r9, QWORD PTR [rax+104]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ mov QWORD PTR [rcx+104], r12
+ ; A[14] * B
+ mulx r10, r9, QWORD PTR [rax+112]
+ mov r12, r13
+ adcx r11, r9
+ adox r12, r10
+ mov QWORD PTR [rcx+112], r11
+ ; A[15] * B
+ mulx r10, r9, QWORD PTR [rax+120]
+ mov r11, r13
+ adcx r12, r9
+ adox r11, r10
+ adcx r11, r13
+ mov QWORD PTR [rcx+120], r12
+ mov QWORD PTR [rcx+128], r11
+ pop r13
+ pop r12
+ ret
+sp_1024_mul_d_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF _WIN64
+; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
+; *
+; * d1 The high order half of the number to divide.
+; * d0 The low order half of the number to divide.
+; * div The dividend.
+; * returns the result of the division.
+; */
+_text SEGMENT READONLY PARA
+div_1024_word_asm_16 PROC
+ mov r9, rdx
+ mov rax, r9
+ mov rdx, rcx
+ div r8
+ ret
+div_1024_word_asm_16 ENDP
+_text ENDS
+ENDIF
+; /* Compare a with b in constant time.
+; *
+; * a A single precision integer.
+; * b A single precision integer.
+; * return -ve, 0 or +ve if a is less than, equal to or greater than b
+; * respectively.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_cmp_16 PROC
+ push r12
+ xor r9, r9
+ mov r8, -1
+ mov rax, -1
+ mov r10, 1
+ mov r11, QWORD PTR [rcx+120]
+ mov r12, QWORD PTR [rdx+120]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+112]
+ mov r12, QWORD PTR [rdx+112]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+104]
+ mov r12, QWORD PTR [rdx+104]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+96]
+ mov r12, QWORD PTR [rdx+96]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+88]
+ mov r12, QWORD PTR [rdx+88]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+80]
+ mov r12, QWORD PTR [rdx+80]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+72]
+ mov r12, QWORD PTR [rdx+72]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+64]
+ mov r12, QWORD PTR [rdx+64]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+56]
+ mov r12, QWORD PTR [rdx+56]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+48]
+ mov r12, QWORD PTR [rdx+48]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+40]
+ mov r12, QWORD PTR [rdx+40]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+32]
+ mov r12, QWORD PTR [rdx+32]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+24]
+ mov r12, QWORD PTR [rdx+24]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+16]
+ mov r12, QWORD PTR [rdx+16]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx+8]
+ mov r12, QWORD PTR [rdx+8]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ mov r11, QWORD PTR [rcx]
+ mov r12, QWORD PTR [rdx]
+ and r11, r8
+ and r12, r8
+ sub r11, r12
+ cmova rax, r10
+ cmovc rax, r8
+ cmovnz r8, r9
+ xor rax, r8
+ pop r12
+ ret
+sp_1024_cmp_16 ENDP
+_text ENDS
+; /* Conditionally copy a into r using the mask m.
+; * m is -1 to copy and 0 when not.
+; *
+; * r A single precision number to copy over.
+; * a A single precision number to copy.
+; * m Mask value to apply.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_cond_copy_16 PROC
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [rcx+16]
+ mov r11, QWORD PTR [rcx+24]
+ xor rax, QWORD PTR [rdx]
+ xor r9, QWORD PTR [rdx+8]
+ xor r10, QWORD PTR [rdx+16]
+ xor r11, QWORD PTR [rdx+24]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ xor QWORD PTR [rcx], rax
+ xor QWORD PTR [rcx+8], r9
+ xor QWORD PTR [rcx+16], r10
+ xor QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov r10, QWORD PTR [rcx+48]
+ mov r11, QWORD PTR [rcx+56]
+ xor rax, QWORD PTR [rdx+32]
+ xor r9, QWORD PTR [rdx+40]
+ xor r10, QWORD PTR [rdx+48]
+ xor r11, QWORD PTR [rdx+56]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ xor QWORD PTR [rcx+32], rax
+ xor QWORD PTR [rcx+40], r9
+ xor QWORD PTR [rcx+48], r10
+ xor QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov r10, QWORD PTR [rcx+80]
+ mov r11, QWORD PTR [rcx+88]
+ xor rax, QWORD PTR [rdx+64]
+ xor r9, QWORD PTR [rdx+72]
+ xor r10, QWORD PTR [rdx+80]
+ xor r11, QWORD PTR [rdx+88]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ xor QWORD PTR [rcx+64], rax
+ xor QWORD PTR [rcx+72], r9
+ xor QWORD PTR [rcx+80], r10
+ xor QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [rcx+112]
+ mov r11, QWORD PTR [rcx+120]
+ xor rax, QWORD PTR [rdx+96]
+ xor r9, QWORD PTR [rdx+104]
+ xor r10, QWORD PTR [rdx+112]
+ xor r11, QWORD PTR [rdx+120]
+ and rax, r8
+ and r9, r8
+ and r10, r8
+ and r11, r8
+ xor QWORD PTR [rcx+96], rax
+ xor QWORD PTR [rcx+104], r9
+ xor QWORD PTR [rcx+112], r10
+ xor QWORD PTR [rcx+120], r11
+ ret
+sp_1024_cond_copy_16 ENDP
+_text ENDS
+; /* Reduce the number back to 1024 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_reduce_16 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ mov r9, rdx
+ xor rsi, rsi
+ ; i = 16
+ mov r10, 16
+ mov r15, QWORD PTR [rcx]
+ mov rdi, QWORD PTR [rcx+8]
+L_1024_mont_loop_16:
+ ; mu = a[i] * mp
+ mov r13, r15
+ imul r13, r8
+ ; a[i+0] += m[0] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9]
+ add r15, rax
+ adc r12, rdx
+ ; a[i+1] += m[1] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+8]
+ mov r15, rdi
+ add r15, rax
+ adc r11, rdx
+ add r15, r12
+ adc r11, 0
+ ; a[i+2] += m[2] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+16]
+ mov rdi, QWORD PTR [rcx+16]
+ add rdi, rax
+ adc r12, rdx
+ add rdi, r11
+ adc r12, 0
+ ; a[i+3] += m[3] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+24]
+ mov r14, QWORD PTR [rcx+24]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+24], r14
+ adc r11, 0
+ ; a[i+4] += m[4] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+32]
+ mov r14, QWORD PTR [rcx+32]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+32], r14
+ adc r12, 0
+ ; a[i+5] += m[5] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+40]
+ mov r14, QWORD PTR [rcx+40]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+40], r14
+ adc r11, 0
+ ; a[i+6] += m[6] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+48]
+ mov r14, QWORD PTR [rcx+48]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+48], r14
+ adc r12, 0
+ ; a[i+7] += m[7] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+56]
+ mov r14, QWORD PTR [rcx+56]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+56], r14
+ adc r11, 0
+ ; a[i+8] += m[8] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+64]
+ mov r14, QWORD PTR [rcx+64]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+64], r14
+ adc r12, 0
+ ; a[i+9] += m[9] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+72]
+ mov r14, QWORD PTR [rcx+72]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+72], r14
+ adc r11, 0
+ ; a[i+10] += m[10] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+80]
+ mov r14, QWORD PTR [rcx+80]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+80], r14
+ adc r12, 0
+ ; a[i+11] += m[11] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+88]
+ mov r14, QWORD PTR [rcx+88]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+88], r14
+ adc r11, 0
+ ; a[i+12] += m[12] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+96]
+ mov r14, QWORD PTR [rcx+96]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+96], r14
+ adc r12, 0
+ ; a[i+13] += m[13] * mu
+ mov rax, r13
+ xor r11, r11
+ mul QWORD PTR [r9+104]
+ mov r14, QWORD PTR [rcx+104]
+ add r14, rax
+ adc r11, rdx
+ add r14, r12
+ mov QWORD PTR [rcx+104], r14
+ adc r11, 0
+ ; a[i+14] += m[14] * mu
+ mov rax, r13
+ xor r12, r12
+ mul QWORD PTR [r9+112]
+ mov r14, QWORD PTR [rcx+112]
+ add r14, rax
+ adc r12, rdx
+ add r14, r11
+ mov QWORD PTR [rcx+112], r14
+ adc r12, 0
+ ; a[i+15] += m[15] * mu
+ mov rax, r13
+ mul QWORD PTR [r9+120]
+ mov r14, QWORD PTR [rcx+120]
+ add r12, rax
+ adc rdx, rsi
+ mov rsi, 0
+ adc rsi, 0
+ add r14, r12
+ mov QWORD PTR [rcx+120], r14
+ adc QWORD PTR [rcx+128], rdx
+ adc rsi, 0
+ ; i -= 1
+ add rcx, 8
+ dec r10
+ jnz L_1024_mont_loop_16
+ mov r14, QWORD PTR [rcx+120]
+ mov QWORD PTR [rcx], r15
+ sub r14, QWORD PTR [r9+120]
+ mov QWORD PTR [rcx+8], rdi
+ sbb r14, r14
+ neg rsi
+ not r14
+ or rsi, r14
+IFDEF _WIN64
+ mov r8, r9
+ mov r9, rsi
+ELSE
+ mov r9, rsi
+ mov r8, r9
+ENDIF
+ mov rdx, rcx
+ mov rcx, rcx
+ sub rcx, 128
+ call sp_1024_cond_sub_16
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_reduce_16 ENDP
+_text ENDS
+; /* Add two Montgomery form numbers (r = a + b % m).
+; *
+; * r Result of addition.
+; * a First number to add in Montogmery form.
+; * b Second number to add in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_add_16 PROC
+ push r12
+ push r13
+ sub rsp, 128
+ mov rax, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [r8]
+ mov r13, 0
+ adc r10, QWORD PTR [r8+8]
+ adc r11, QWORD PTR [r8+16]
+ adc r12, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov rax, QWORD PTR [rdx+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov r11, QWORD PTR [rdx+48]
+ mov r12, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [r8+32]
+ adc r10, QWORD PTR [r8+40]
+ adc r11, QWORD PTR [r8+48]
+ adc r12, QWORD PTR [r8+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov QWORD PTR [rcx+48], r11
+ mov QWORD PTR [rcx+56], r12
+ mov rax, QWORD PTR [rdx+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov r11, QWORD PTR [rdx+80]
+ mov r12, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [r8+64]
+ adc r10, QWORD PTR [r8+72]
+ adc r11, QWORD PTR [r8+80]
+ adc r12, QWORD PTR [r8+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov QWORD PTR [rcx+80], r11
+ mov QWORD PTR [rcx+88], r12
+ mov rax, QWORD PTR [rdx+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov r11, QWORD PTR [rdx+112]
+ mov r12, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [r8+96]
+ adc r10, QWORD PTR [r8+104]
+ adc r11, QWORD PTR [r8+112]
+ adc r12, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov QWORD PTR [rcx+112], r11
+ mov QWORD PTR [rcx+120], r12
+ sbb r13, 0
+ sub r12, QWORD PTR [r9+120]
+ sbb r12, r12
+ not r12
+ or r13, r12
+ mov r11, QWORD PTR [r9]
+ mov r12, QWORD PTR [r9+8]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp], r11
+ mov QWORD PTR [rsp+8], r12
+ mov r11, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [r9+24]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+16], r11
+ mov QWORD PTR [rsp+24], r12
+ mov r11, QWORD PTR [r9+32]
+ mov r12, QWORD PTR [r9+40]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+32], r11
+ mov QWORD PTR [rsp+40], r12
+ mov r11, QWORD PTR [r9+48]
+ mov r12, QWORD PTR [r9+56]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+48], r11
+ mov QWORD PTR [rsp+56], r12
+ mov r11, QWORD PTR [r9+64]
+ mov r12, QWORD PTR [r9+72]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+64], r11
+ mov QWORD PTR [rsp+72], r12
+ mov r11, QWORD PTR [r9+80]
+ mov r12, QWORD PTR [r9+88]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+80], r11
+ mov QWORD PTR [rsp+88], r12
+ mov r11, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [r9+104]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+96], r11
+ mov QWORD PTR [rsp+104], r12
+ mov r11, QWORD PTR [r9+112]
+ mov r12, QWORD PTR [r9+120]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+112], r11
+ mov QWORD PTR [rsp+120], r12
+ mov rax, QWORD PTR [rcx]
+ mov r10, QWORD PTR [rcx+8]
+ sub rax, QWORD PTR [rsp]
+ sbb r10, QWORD PTR [rsp+8]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [rcx+16]
+ mov r10, QWORD PTR [rcx+24]
+ sbb rax, QWORD PTR [rsp+16]
+ sbb r10, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [rcx+40]
+ sbb rax, QWORD PTR [rsp+32]
+ sbb r10, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [rcx+48]
+ mov r10, QWORD PTR [rcx+56]
+ sbb rax, QWORD PTR [rsp+48]
+ sbb r10, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ mov rax, QWORD PTR [rcx+64]
+ mov r10, QWORD PTR [rcx+72]
+ sbb rax, QWORD PTR [rsp+64]
+ sbb r10, QWORD PTR [rsp+72]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov rax, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [rcx+88]
+ sbb rax, QWORD PTR [rsp+80]
+ sbb r10, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r10
+ mov rax, QWORD PTR [rcx+96]
+ mov r10, QWORD PTR [rcx+104]
+ sbb rax, QWORD PTR [rsp+96]
+ sbb r10, QWORD PTR [rsp+104]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov rax, QWORD PTR [rcx+112]
+ mov r10, QWORD PTR [rcx+120]
+ sbb rax, QWORD PTR [rsp+112]
+ sbb r10, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r10
+ add rsp, 128
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_add_16 ENDP
+_text ENDS
+; /* Double a Montgomery form number (r = a + a % m).
+; *
+; * r Result of addition.
+; * a Number to souble in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_dbl_16 PROC
+ push r12
+ sub rsp, 128
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ mov r11, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ mov r11, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov r11, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ sub rax, QWORD PTR [rsp]
+ sbb r9, QWORD PTR [rsp+8]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ sbb rax, QWORD PTR [rsp+16]
+ sbb r9, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ sbb rax, QWORD PTR [rsp+32]
+ sbb r9, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ sbb rax, QWORD PTR [rsp+48]
+ sbb r9, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ sbb rax, QWORD PTR [rsp+64]
+ sbb r9, QWORD PTR [rsp+72]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ sbb rax, QWORD PTR [rsp+80]
+ sbb r9, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ sbb rax, QWORD PTR [rsp+96]
+ sbb r9, QWORD PTR [rsp+104]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ sbb rax, QWORD PTR [rsp+112]
+ sbb r9, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ add rsp, 128
+ pop r12
+ ret
+sp_1024_mont_dbl_16 ENDP
+_text ENDS
+; /* Triple a Montgomery form number (r = a + a + a % m).
+; *
+; * r Result of addition.
+; * a Number to souble in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_tpl_16 PROC
+ push r12
+ sub rsp, 128
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ mov r11, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ mov r11, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov r11, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ sub rax, QWORD PTR [rsp]
+ sbb r9, QWORD PTR [rsp+8]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ sbb rax, QWORD PTR [rsp+16]
+ sbb r9, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ sbb rax, QWORD PTR [rsp+32]
+ sbb r9, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ sbb rax, QWORD PTR [rsp+48]
+ sbb r9, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ sbb rax, QWORD PTR [rsp+64]
+ sbb r9, QWORD PTR [rsp+72]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ sbb rax, QWORD PTR [rsp+80]
+ sbb r9, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ sbb rax, QWORD PTR [rsp+96]
+ sbb r9, QWORD PTR [rsp+104]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ sbb rax, QWORD PTR [rsp+112]
+ sbb r9, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [rcx+16]
+ mov r11, QWORD PTR [rcx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov r10, QWORD PTR [rcx+48]
+ mov r11, QWORD PTR [rcx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov r10, QWORD PTR [rcx+80]
+ mov r11, QWORD PTR [rcx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [rcx+112]
+ mov r11, QWORD PTR [rcx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp], r10
+ mov QWORD PTR [rsp+8], r11
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+16], r10
+ mov QWORD PTR [rsp+24], r11
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+32], r10
+ mov QWORD PTR [rsp+40], r11
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+48], r10
+ mov QWORD PTR [rsp+56], r11
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+64], r10
+ mov QWORD PTR [rsp+72], r11
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+80], r10
+ mov QWORD PTR [rsp+88], r11
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+96], r10
+ mov QWORD PTR [rsp+104], r11
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ and r10, r12
+ and r11, r12
+ mov QWORD PTR [rsp+112], r10
+ mov QWORD PTR [rsp+120], r11
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ sub rax, QWORD PTR [rsp]
+ sbb r9, QWORD PTR [rsp+8]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ sbb rax, QWORD PTR [rsp+16]
+ sbb r9, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ sbb rax, QWORD PTR [rsp+32]
+ sbb r9, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ sbb rax, QWORD PTR [rsp+48]
+ sbb r9, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ sbb rax, QWORD PTR [rsp+64]
+ sbb r9, QWORD PTR [rsp+72]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ sbb rax, QWORD PTR [rsp+80]
+ sbb r9, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ sbb rax, QWORD PTR [rsp+96]
+ sbb r9, QWORD PTR [rsp+104]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ sbb rax, QWORD PTR [rsp+112]
+ sbb r9, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ add rsp, 128
+ pop r12
+ ret
+sp_1024_mont_tpl_16 ENDP
+_text ENDS
+; /* Subtract two Montgomery form numbers (r = a - b % m).
+; *
+; * r Result of addition.
+; * a First number to add in Montogmery form.
+; * b Second number to add in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_sub_16 PROC
+ push r12
+ push r13
+ sub rsp, 128
+ mov rax, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ sub rax, QWORD PTR [r8]
+ mov r13, 0
+ sbb r10, QWORD PTR [r8+8]
+ sbb r11, QWORD PTR [r8+16]
+ sbb r12, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov rax, QWORD PTR [rdx+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov r11, QWORD PTR [rdx+48]
+ mov r12, QWORD PTR [rdx+56]
+ sbb rax, QWORD PTR [r8+32]
+ sbb r10, QWORD PTR [r8+40]
+ sbb r11, QWORD PTR [r8+48]
+ sbb r12, QWORD PTR [r8+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov QWORD PTR [rcx+48], r11
+ mov QWORD PTR [rcx+56], r12
+ mov rax, QWORD PTR [rdx+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov r11, QWORD PTR [rdx+80]
+ mov r12, QWORD PTR [rdx+88]
+ sbb rax, QWORD PTR [r8+64]
+ sbb r10, QWORD PTR [r8+72]
+ sbb r11, QWORD PTR [r8+80]
+ sbb r12, QWORD PTR [r8+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov QWORD PTR [rcx+80], r11
+ mov QWORD PTR [rcx+88], r12
+ mov rax, QWORD PTR [rdx+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov r11, QWORD PTR [rdx+112]
+ mov r12, QWORD PTR [rdx+120]
+ sbb rax, QWORD PTR [r8+96]
+ sbb r10, QWORD PTR [r8+104]
+ sbb r11, QWORD PTR [r8+112]
+ sbb r12, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov QWORD PTR [rcx+112], r11
+ mov QWORD PTR [rcx+120], r12
+ sbb r13, 0
+ mov r11, QWORD PTR [r9]
+ mov r12, QWORD PTR [r9+8]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp], r11
+ mov QWORD PTR [rsp+8], r12
+ mov r11, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [r9+24]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+16], r11
+ mov QWORD PTR [rsp+24], r12
+ mov r11, QWORD PTR [r9+32]
+ mov r12, QWORD PTR [r9+40]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+32], r11
+ mov QWORD PTR [rsp+40], r12
+ mov r11, QWORD PTR [r9+48]
+ mov r12, QWORD PTR [r9+56]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+48], r11
+ mov QWORD PTR [rsp+56], r12
+ mov r11, QWORD PTR [r9+64]
+ mov r12, QWORD PTR [r9+72]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+64], r11
+ mov QWORD PTR [rsp+72], r12
+ mov r11, QWORD PTR [r9+80]
+ mov r12, QWORD PTR [r9+88]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+80], r11
+ mov QWORD PTR [rsp+88], r12
+ mov r11, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [r9+104]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+96], r11
+ mov QWORD PTR [rsp+104], r12
+ mov r11, QWORD PTR [r9+112]
+ mov r12, QWORD PTR [r9+120]
+ and r11, r13
+ and r12, r13
+ mov QWORD PTR [rsp+112], r11
+ mov QWORD PTR [rsp+120], r12
+ mov rax, QWORD PTR [rcx]
+ mov r10, QWORD PTR [rcx+8]
+ add rax, QWORD PTR [rsp]
+ adc r10, QWORD PTR [rsp+8]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [rcx+16]
+ mov r10, QWORD PTR [rcx+24]
+ adc rax, QWORD PTR [rsp+16]
+ adc r10, QWORD PTR [rsp+24]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [rcx+40]
+ adc rax, QWORD PTR [rsp+32]
+ adc r10, QWORD PTR [rsp+40]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [rcx+48]
+ mov r10, QWORD PTR [rcx+56]
+ adc rax, QWORD PTR [rsp+48]
+ adc r10, QWORD PTR [rsp+56]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ mov rax, QWORD PTR [rcx+64]
+ mov r10, QWORD PTR [rcx+72]
+ adc rax, QWORD PTR [rsp+64]
+ adc r10, QWORD PTR [rsp+72]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov rax, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [rcx+88]
+ adc rax, QWORD PTR [rsp+80]
+ adc r10, QWORD PTR [rsp+88]
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r10
+ mov rax, QWORD PTR [rcx+96]
+ mov r10, QWORD PTR [rcx+104]
+ adc rax, QWORD PTR [rsp+96]
+ adc r10, QWORD PTR [rsp+104]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov rax, QWORD PTR [rcx+112]
+ mov r10, QWORD PTR [rcx+120]
+ adc rax, QWORD PTR [rsp+112]
+ adc r10, QWORD PTR [rsp+120]
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r10
+ add rsp, 128
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_sub_16 ENDP
+_text ENDS
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_div2_16 PROC
+ push r12
+ push r13
+ sub rsp, 128
+ mov r13, QWORD PTR [rdx]
+ xor r12, r12
+ mov rax, r13
+ and r13, 1
+ neg r13
+ mov r10, QWORD PTR [r8]
+ and r10, r13
+ mov QWORD PTR [rsp], r10
+ mov r10, QWORD PTR [r8+8]
+ and r10, r13
+ mov QWORD PTR [rsp+8], r10
+ mov r10, QWORD PTR [r8+16]
+ and r10, r13
+ mov QWORD PTR [rsp+16], r10
+ mov r10, QWORD PTR [r8+24]
+ and r10, r13
+ mov QWORD PTR [rsp+24], r10
+ mov r10, QWORD PTR [r8+32]
+ and r10, r13
+ mov QWORD PTR [rsp+32], r10
+ mov r10, QWORD PTR [r8+40]
+ and r10, r13
+ mov QWORD PTR [rsp+40], r10
+ mov r10, QWORD PTR [r8+48]
+ and r10, r13
+ mov QWORD PTR [rsp+48], r10
+ mov r10, QWORD PTR [r8+56]
+ and r10, r13
+ mov QWORD PTR [rsp+56], r10
+ mov r10, QWORD PTR [r8+64]
+ and r10, r13
+ mov QWORD PTR [rsp+64], r10
+ mov r10, QWORD PTR [r8+72]
+ and r10, r13
+ mov QWORD PTR [rsp+72], r10
+ mov r10, QWORD PTR [r8+80]
+ and r10, r13
+ mov QWORD PTR [rsp+80], r10
+ mov r10, QWORD PTR [r8+88]
+ and r10, r13
+ mov QWORD PTR [rsp+88], r10
+ mov r10, QWORD PTR [r8+96]
+ and r10, r13
+ mov QWORD PTR [rsp+96], r10
+ mov r10, QWORD PTR [r8+104]
+ and r10, r13
+ mov QWORD PTR [rsp+104], r10
+ mov r10, QWORD PTR [r8+112]
+ and r10, r13
+ mov QWORD PTR [rsp+112], r10
+ mov r10, QWORD PTR [r8+120]
+ and r10, r13
+ mov QWORD PTR [rsp+120], r10
+ add QWORD PTR [rsp], rax
+ mov rax, QWORD PTR [rdx+8]
+ adc QWORD PTR [rsp+8], rax
+ mov rax, QWORD PTR [rdx+16]
+ adc QWORD PTR [rsp+16], rax
+ mov rax, QWORD PTR [rdx+24]
+ adc QWORD PTR [rsp+24], rax
+ mov rax, QWORD PTR [rdx+32]
+ adc QWORD PTR [rsp+32], rax
+ mov rax, QWORD PTR [rdx+40]
+ adc QWORD PTR [rsp+40], rax
+ mov rax, QWORD PTR [rdx+48]
+ adc QWORD PTR [rsp+48], rax
+ mov rax, QWORD PTR [rdx+56]
+ adc QWORD PTR [rsp+56], rax
+ mov rax, QWORD PTR [rdx+64]
+ adc QWORD PTR [rsp+64], rax
+ mov rax, QWORD PTR [rdx+72]
+ adc QWORD PTR [rsp+72], rax
+ mov rax, QWORD PTR [rdx+80]
+ adc QWORD PTR [rsp+80], rax
+ mov rax, QWORD PTR [rdx+88]
+ adc QWORD PTR [rsp+88], rax
+ mov rax, QWORD PTR [rdx+96]
+ adc QWORD PTR [rsp+96], rax
+ mov rax, QWORD PTR [rdx+104]
+ adc QWORD PTR [rsp+104], rax
+ mov rax, QWORD PTR [rdx+112]
+ adc QWORD PTR [rsp+112], rax
+ mov rax, QWORD PTR [rdx+120]
+ adc QWORD PTR [rsp+120], rax
+ adc r12, 0
+ mov rax, QWORD PTR [rsp]
+ mov r9, QWORD PTR [rsp+8]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx], rax
+ mov rax, QWORD PTR [rsp+16]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+8], r9
+ mov r9, QWORD PTR [rsp+24]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+16], rax
+ mov rax, QWORD PTR [rsp+32]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+24], r9
+ mov r9, QWORD PTR [rsp+40]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+32], rax
+ mov rax, QWORD PTR [rsp+48]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+40], r9
+ mov r9, QWORD PTR [rsp+56]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+48], rax
+ mov rax, QWORD PTR [rsp+64]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+56], r9
+ mov r9, QWORD PTR [rsp+72]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+64], rax
+ mov rax, QWORD PTR [rsp+80]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+72], r9
+ mov r9, QWORD PTR [rsp+88]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+80], rax
+ mov rax, QWORD PTR [rsp+96]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+88], r9
+ mov r9, QWORD PTR [rsp+104]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+96], rax
+ mov rax, QWORD PTR [rsp+112]
+ shrd r9, rax, 1
+ mov QWORD PTR [rcx+104], r9
+ mov r9, QWORD PTR [rsp+120]
+ shrd rax, r9, 1
+ mov QWORD PTR [rcx+112], rax
+ shrd r9, r12, 1
+ mov QWORD PTR [rcx+120], r9
+ add rsp, 128
+ pop r13
+ pop r12
+ ret
+sp_1024_div2_16 ENDP
+_text ENDS
+; /* Sub b from a into r. (r = a - b)
+; *
+; * r A single precision integer.
+; * a A single precision integer.
+; * b A single precision integer.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_sub_16 PROC
+ mov r9, QWORD PTR [rdx]
+ xor rax, rax
+ sub r9, QWORD PTR [r8]
+ mov r10, QWORD PTR [rdx+8]
+ mov QWORD PTR [rcx], r9
+ sbb r10, QWORD PTR [r8+8]
+ mov r9, QWORD PTR [rdx+16]
+ mov QWORD PTR [rcx+8], r10
+ sbb r9, QWORD PTR [r8+16]
+ mov r10, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx+16], r9
+ sbb r10, QWORD PTR [r8+24]
+ mov r9, QWORD PTR [rdx+32]
+ mov QWORD PTR [rcx+24], r10
+ sbb r9, QWORD PTR [r8+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov QWORD PTR [rcx+32], r9
+ sbb r10, QWORD PTR [r8+40]
+ mov r9, QWORD PTR [rdx+48]
+ mov QWORD PTR [rcx+40], r10
+ sbb r9, QWORD PTR [r8+48]
+ mov r10, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+48], r9
+ sbb r10, QWORD PTR [r8+56]
+ mov r9, QWORD PTR [rdx+64]
+ mov QWORD PTR [rcx+56], r10
+ sbb r9, QWORD PTR [r8+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov QWORD PTR [rcx+64], r9
+ sbb r10, QWORD PTR [r8+72]
+ mov r9, QWORD PTR [rdx+80]
+ mov QWORD PTR [rcx+72], r10
+ sbb r9, QWORD PTR [r8+80]
+ mov r10, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+80], r9
+ sbb r10, QWORD PTR [r8+88]
+ mov r9, QWORD PTR [rdx+96]
+ mov QWORD PTR [rcx+88], r10
+ sbb r9, QWORD PTR [r8+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov QWORD PTR [rcx+96], r9
+ sbb r10, QWORD PTR [r8+104]
+ mov r9, QWORD PTR [rdx+112]
+ mov QWORD PTR [rcx+104], r10
+ sbb r9, QWORD PTR [r8+112]
+ mov r10, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+112], r9
+ sbb r10, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+120], r10
+ sbb rax, 0
+ ret
+sp_1024_sub_16 ENDP
+_text ENDS
+IFDEF HAVE_INTEL_AVX2
+; /* Reduce the number back to 1024 bits using Montgomery reduction.
+; *
+; * a A single precision number to reduce in place.
+; * m The single precision number representing the modulus.
+; * mp The digit representing the negative inverse of m mod 2^n.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_reduce_avx2_16 PROC
+ push r12
+ push r13
+ push r14
+ push r15
+ push rdi
+ push rsi
+ push rbx
+ push rbp
+ mov r9, rcx
+ mov r10, rdx
+ xor rbp, rbp
+ ; i = 16
+ mov r11, 16
+ mov r15, QWORD PTR [r9]
+ mov rdi, QWORD PTR [r9+8]
+ mov rsi, QWORD PTR [r9+16]
+ mov rbx, QWORD PTR [r9+24]
+ add r9, 64
+ xor rbp, rbp
+L_1024_mont_loop_avx2_16:
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-32]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-24]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-24], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9+-8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-16], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-8], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+8]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+16]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+8], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+24]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+16], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+32]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+24], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+40]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+32], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+48]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+40], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+56]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+48], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+64]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+56], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+64], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; mu = a[i] * mp
+ mov rdx, r15
+ mov r12, r15
+ imul rdx, r8
+ xor r14, r14
+ ; a[i+0] += m[0] * mu
+ mulx rcx, rax, QWORD PTR [r10]
+ mov r15, rdi
+ adcx r12, rax
+ adox r15, rcx
+ ; a[i+1] += m[1] * mu
+ mulx rcx, rax, QWORD PTR [r10+8]
+ mov rdi, rsi
+ adcx r15, rax
+ adox rdi, rcx
+ ; a[i+2] += m[2] * mu
+ mulx rcx, rax, QWORD PTR [r10+16]
+ mov rsi, rbx
+ adcx rdi, rax
+ adox rsi, rcx
+ ; a[i+3] += m[3] * mu
+ mulx rcx, rax, QWORD PTR [r10+24]
+ mov rbx, QWORD PTR [r9+-24]
+ adcx rsi, rax
+ adox rbx, rcx
+ ; a[i+4] += m[4] * mu
+ mulx rcx, rax, QWORD PTR [r10+32]
+ mov r13, QWORD PTR [r9+-16]
+ adcx rbx, rax
+ adox r13, rcx
+ ; a[i+5] += m[5] * mu
+ mulx rcx, rax, QWORD PTR [r10+40]
+ mov r12, QWORD PTR [r9+-8]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+-16], r13
+ ; a[i+6] += m[6] * mu
+ mulx rcx, rax, QWORD PTR [r10+48]
+ mov r13, QWORD PTR [r9]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+-8], r12
+ ; a[i+7] += m[7] * mu
+ mulx rcx, rax, QWORD PTR [r10+56]
+ mov r12, QWORD PTR [r9+8]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9], r13
+ ; a[i+8] += m[8] * mu
+ mulx rcx, rax, QWORD PTR [r10+64]
+ mov r13, QWORD PTR [r9+16]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+8], r12
+ ; a[i+9] += m[9] * mu
+ mulx rcx, rax, QWORD PTR [r10+72]
+ mov r12, QWORD PTR [r9+24]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+16], r13
+ ; a[i+10] += m[10] * mu
+ mulx rcx, rax, QWORD PTR [r10+80]
+ mov r13, QWORD PTR [r9+32]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+24], r12
+ ; a[i+11] += m[11] * mu
+ mulx rcx, rax, QWORD PTR [r10+88]
+ mov r12, QWORD PTR [r9+40]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+32], r13
+ ; a[i+12] += m[12] * mu
+ mulx rcx, rax, QWORD PTR [r10+96]
+ mov r13, QWORD PTR [r9+48]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+40], r12
+ ; a[i+13] += m[13] * mu
+ mulx rcx, rax, QWORD PTR [r10+104]
+ mov r12, QWORD PTR [r9+56]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+48], r13
+ ; a[i+14] += m[14] * mu
+ mulx rcx, rax, QWORD PTR [r10+112]
+ mov r13, QWORD PTR [r9+64]
+ adcx r12, rax
+ adox r13, rcx
+ mov QWORD PTR [r9+56], r12
+ ; a[i+15] += m[15] * mu
+ mulx rcx, rax, QWORD PTR [r10+120]
+ mov r12, QWORD PTR [r9+72]
+ adcx r13, rax
+ adox r12, rcx
+ mov QWORD PTR [r9+64], r13
+ adcx r12, rbp
+ mov rbp, r14
+ mov QWORD PTR [r9+72], r12
+ adox rbp, r14
+ adcx rbp, r14
+ ; a += 2
+ add r9, 16
+ ; i -= 2
+ sub r11, 2
+ jnz L_1024_mont_loop_avx2_16
+ sub r9, 64
+ sub r12, QWORD PTR [r10+120]
+ mov r8, r9
+ sbb r12, r12
+ neg rbp
+ not r12
+ or rbp, r12
+ sub r9, 128
+ mov rcx, QWORD PTR [r10]
+ mov rdx, r15
+ pext rcx, rcx, rbp
+ sub rdx, rcx
+ mov rcx, QWORD PTR [r10+8]
+ mov rax, rdi
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+16]
+ mov rcx, rsi
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+8], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+24]
+ mov rdx, rbx
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+16], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+32]
+ mov rax, QWORD PTR [r8+32]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+24], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+40]
+ mov rcx, QWORD PTR [r8+40]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+32], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+48]
+ mov rdx, QWORD PTR [r8+48]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+40], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+56]
+ mov rax, QWORD PTR [r8+56]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+48], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+64]
+ mov rcx, QWORD PTR [r8+64]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+56], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+72]
+ mov rdx, QWORD PTR [r8+72]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+64], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+80]
+ mov rax, QWORD PTR [r8+80]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+72], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+88]
+ mov rcx, QWORD PTR [r8+88]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+80], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+96]
+ mov rdx, QWORD PTR [r8+96]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+88], rcx
+ sbb rdx, rax
+ mov rcx, QWORD PTR [r10+104]
+ mov rax, QWORD PTR [r8+104]
+ pext rcx, rcx, rbp
+ mov QWORD PTR [r9+96], rdx
+ sbb rax, rcx
+ mov rdx, QWORD PTR [r10+112]
+ mov rcx, QWORD PTR [r8+112]
+ pext rdx, rdx, rbp
+ mov QWORD PTR [r9+104], rax
+ sbb rcx, rdx
+ mov rax, QWORD PTR [r10+120]
+ mov rdx, QWORD PTR [r8+120]
+ pext rax, rax, rbp
+ mov QWORD PTR [r9+112], rcx
+ sbb rdx, rax
+ mov QWORD PTR [r9+120], rdx
+ pop rbp
+ pop rbx
+ pop rsi
+ pop rdi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_reduce_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Add two Montgomery form numbers (r = a + b % m).
+; *
+; * r Result of addition.
+; * a First number to add in Montogmery form.
+; * b Second number to add in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_add_avx2_16 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [r8]
+ mov r13, 0
+ adc r10, QWORD PTR [r8+8]
+ adc r11, QWORD PTR [r8+16]
+ adc r12, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov rax, QWORD PTR [rdx+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov r11, QWORD PTR [rdx+48]
+ mov r12, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [r8+32]
+ adc r10, QWORD PTR [r8+40]
+ adc r11, QWORD PTR [r8+48]
+ adc r12, QWORD PTR [r8+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov QWORD PTR [rcx+48], r11
+ mov QWORD PTR [rcx+56], r12
+ mov rax, QWORD PTR [rdx+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov r11, QWORD PTR [rdx+80]
+ mov r12, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [r8+64]
+ adc r10, QWORD PTR [r8+72]
+ adc r11, QWORD PTR [r8+80]
+ adc r12, QWORD PTR [r8+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov QWORD PTR [rcx+80], r11
+ mov QWORD PTR [rcx+88], r12
+ mov rax, QWORD PTR [rdx+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov r11, QWORD PTR [rdx+112]
+ mov r12, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [r8+96]
+ adc r10, QWORD PTR [r8+104]
+ adc r11, QWORD PTR [r8+112]
+ adc r12, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov QWORD PTR [rcx+112], r11
+ mov QWORD PTR [rcx+120], r12
+ sbb r13, 0
+ sub r12, QWORD PTR [r9+120]
+ sbb r12, r12
+ not r12
+ or r13, r12
+ mov r11, QWORD PTR [r9]
+ mov r12, QWORD PTR [r9+8]
+ mov rax, QWORD PTR [rcx]
+ mov r10, QWORD PTR [rcx+8]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sub rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov r11, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [r9+24]
+ mov rax, QWORD PTR [rcx+16]
+ mov r10, QWORD PTR [rcx+24]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov r11, QWORD PTR [r9+32]
+ mov r12, QWORD PTR [r9+40]
+ mov rax, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [rcx+40]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov r11, QWORD PTR [r9+48]
+ mov r12, QWORD PTR [r9+56]
+ mov rax, QWORD PTR [rcx+48]
+ mov r10, QWORD PTR [rcx+56]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ mov r11, QWORD PTR [r9+64]
+ mov r12, QWORD PTR [r9+72]
+ mov rax, QWORD PTR [rcx+64]
+ mov r10, QWORD PTR [rcx+72]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov r11, QWORD PTR [r9+80]
+ mov r12, QWORD PTR [r9+88]
+ mov rax, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [rcx+88]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r10
+ mov r11, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [r9+104]
+ mov rax, QWORD PTR [rcx+96]
+ mov r10, QWORD PTR [rcx+104]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov r11, QWORD PTR [r9+112]
+ mov r12, QWORD PTR [r9+120]
+ mov rax, QWORD PTR [rcx+112]
+ mov r10, QWORD PTR [rcx+120]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ sbb rax, r11
+ sbb r10, r12
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r10
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_add_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Double a Montgomery form number (r = a + a % m).
+; *
+; * r Result of addition.
+; * a Number to souble in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_dbl_avx2_16 PROC
+ push r12
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ mov r11, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ mov r11, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov r11, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sub rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ pop r12
+ ret
+sp_1024_mont_dbl_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Triple a Montgomery form number (r = a + a + a % m).
+; *
+; * r Result of addition.
+; * a Number to souble in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_tpl_avx2_16 PROC
+ push r12
+ mov rax, QWORD PTR [rdx]
+ mov r9, QWORD PTR [rdx+8]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rdx+32]
+ mov r9, QWORD PTR [rdx+40]
+ mov r10, QWORD PTR [rdx+48]
+ mov r11, QWORD PTR [rdx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rdx+64]
+ mov r9, QWORD PTR [rdx+72]
+ mov r10, QWORD PTR [rdx+80]
+ mov r11, QWORD PTR [rdx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rdx+96]
+ mov r9, QWORD PTR [rdx+104]
+ mov r10, QWORD PTR [rdx+112]
+ mov r11, QWORD PTR [rdx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sub rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ mov r10, QWORD PTR [rcx+16]
+ mov r11, QWORD PTR [rcx+24]
+ add rax, QWORD PTR [rdx]
+ mov r12, 0
+ adc r9, QWORD PTR [rdx+8]
+ adc r10, QWORD PTR [rdx+16]
+ adc r11, QWORD PTR [rdx+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ mov r10, QWORD PTR [rcx+48]
+ mov r11, QWORD PTR [rcx+56]
+ adc rax, QWORD PTR [rdx+32]
+ adc r9, QWORD PTR [rdx+40]
+ adc r10, QWORD PTR [rdx+48]
+ adc r11, QWORD PTR [rdx+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ mov r10, QWORD PTR [rcx+80]
+ mov r11, QWORD PTR [rcx+88]
+ adc rax, QWORD PTR [rdx+64]
+ adc r9, QWORD PTR [rdx+72]
+ adc r10, QWORD PTR [rdx+80]
+ adc r11, QWORD PTR [rdx+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ mov r10, QWORD PTR [rcx+112]
+ mov r11, QWORD PTR [rcx+120]
+ adc rax, QWORD PTR [rdx+96]
+ adc r9, QWORD PTR [rdx+104]
+ adc r10, QWORD PTR [rdx+112]
+ adc r11, QWORD PTR [rdx+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ sbb r12, 0
+ sub r11, QWORD PTR [r8+120]
+ sbb r11, r11
+ not r11
+ or r12, r11
+ mov r10, QWORD PTR [r8]
+ mov r11, QWORD PTR [r8+8]
+ mov rax, QWORD PTR [rcx]
+ mov r9, QWORD PTR [rcx+8]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sub rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r9
+ mov r10, QWORD PTR [r8+16]
+ mov r11, QWORD PTR [r8+24]
+ mov rax, QWORD PTR [rcx+16]
+ mov r9, QWORD PTR [rcx+24]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r9
+ mov r10, QWORD PTR [r8+32]
+ mov r11, QWORD PTR [r8+40]
+ mov rax, QWORD PTR [rcx+32]
+ mov r9, QWORD PTR [rcx+40]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r9
+ mov r10, QWORD PTR [r8+48]
+ mov r11, QWORD PTR [r8+56]
+ mov rax, QWORD PTR [rcx+48]
+ mov r9, QWORD PTR [rcx+56]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r9
+ mov r10, QWORD PTR [r8+64]
+ mov r11, QWORD PTR [r8+72]
+ mov rax, QWORD PTR [rcx+64]
+ mov r9, QWORD PTR [rcx+72]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r9
+ mov r10, QWORD PTR [r8+80]
+ mov r11, QWORD PTR [r8+88]
+ mov rax, QWORD PTR [rcx+80]
+ mov r9, QWORD PTR [rcx+88]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r9
+ mov r10, QWORD PTR [r8+96]
+ mov r11, QWORD PTR [r8+104]
+ mov rax, QWORD PTR [rcx+96]
+ mov r9, QWORD PTR [rcx+104]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r9
+ mov r10, QWORD PTR [r8+112]
+ mov r11, QWORD PTR [r8+120]
+ mov rax, QWORD PTR [rcx+112]
+ mov r9, QWORD PTR [rcx+120]
+ pext r10, r10, r12
+ pext r11, r11, r12
+ sbb rax, r10
+ sbb r9, r11
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r9
+ pop r12
+ ret
+sp_1024_mont_tpl_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Subtract two Montgomery form numbers (r = a - b % m).
+; *
+; * r Result of addition.
+; * a First number to add in Montogmery form.
+; * b Second number to add in Montogmery form.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_mont_sub_avx2_16 PROC
+ push r12
+ push r13
+ mov rax, QWORD PTR [rdx]
+ mov r10, QWORD PTR [rdx+8]
+ mov r11, QWORD PTR [rdx+16]
+ mov r12, QWORD PTR [rdx+24]
+ sub rax, QWORD PTR [r8]
+ mov r13, 0
+ sbb r10, QWORD PTR [r8+8]
+ sbb r11, QWORD PTR [r8+16]
+ sbb r12, QWORD PTR [r8+24]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov QWORD PTR [rcx+16], r11
+ mov QWORD PTR [rcx+24], r12
+ mov rax, QWORD PTR [rdx+32]
+ mov r10, QWORD PTR [rdx+40]
+ mov r11, QWORD PTR [rdx+48]
+ mov r12, QWORD PTR [rdx+56]
+ sbb rax, QWORD PTR [r8+32]
+ sbb r10, QWORD PTR [r8+40]
+ sbb r11, QWORD PTR [r8+48]
+ sbb r12, QWORD PTR [r8+56]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov QWORD PTR [rcx+48], r11
+ mov QWORD PTR [rcx+56], r12
+ mov rax, QWORD PTR [rdx+64]
+ mov r10, QWORD PTR [rdx+72]
+ mov r11, QWORD PTR [rdx+80]
+ mov r12, QWORD PTR [rdx+88]
+ sbb rax, QWORD PTR [r8+64]
+ sbb r10, QWORD PTR [r8+72]
+ sbb r11, QWORD PTR [r8+80]
+ sbb r12, QWORD PTR [r8+88]
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov QWORD PTR [rcx+80], r11
+ mov QWORD PTR [rcx+88], r12
+ mov rax, QWORD PTR [rdx+96]
+ mov r10, QWORD PTR [rdx+104]
+ mov r11, QWORD PTR [rdx+112]
+ mov r12, QWORD PTR [rdx+120]
+ sbb rax, QWORD PTR [r8+96]
+ sbb r10, QWORD PTR [r8+104]
+ sbb r11, QWORD PTR [r8+112]
+ sbb r12, QWORD PTR [r8+120]
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov QWORD PTR [rcx+112], r11
+ mov QWORD PTR [rcx+120], r12
+ sbb r13, 0
+ mov r11, QWORD PTR [r9]
+ mov r12, QWORD PTR [r9+8]
+ mov rax, QWORD PTR [rcx]
+ mov r10, QWORD PTR [rcx+8]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ add rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov r11, QWORD PTR [r9+16]
+ mov r12, QWORD PTR [r9+24]
+ mov rax, QWORD PTR [rcx+16]
+ mov r10, QWORD PTR [rcx+24]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov r11, QWORD PTR [r9+32]
+ mov r12, QWORD PTR [r9+40]
+ mov rax, QWORD PTR [rcx+32]
+ mov r10, QWORD PTR [rcx+40]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov r11, QWORD PTR [r9+48]
+ mov r12, QWORD PTR [r9+56]
+ mov rax, QWORD PTR [rcx+48]
+ mov r10, QWORD PTR [rcx+56]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ mov r11, QWORD PTR [r9+64]
+ mov r12, QWORD PTR [r9+72]
+ mov rax, QWORD PTR [rcx+64]
+ mov r10, QWORD PTR [rcx+72]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+64], rax
+ mov QWORD PTR [rcx+72], r10
+ mov r11, QWORD PTR [r9+80]
+ mov r12, QWORD PTR [r9+88]
+ mov rax, QWORD PTR [rcx+80]
+ mov r10, QWORD PTR [rcx+88]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+80], rax
+ mov QWORD PTR [rcx+88], r10
+ mov r11, QWORD PTR [r9+96]
+ mov r12, QWORD PTR [r9+104]
+ mov rax, QWORD PTR [rcx+96]
+ mov r10, QWORD PTR [rcx+104]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+96], rax
+ mov QWORD PTR [rcx+104], r10
+ mov r11, QWORD PTR [r9+112]
+ mov r12, QWORD PTR [r9+120]
+ mov rax, QWORD PTR [rcx+112]
+ mov r10, QWORD PTR [rcx+120]
+ pext r11, r11, r13
+ pext r12, r12, r13
+ adc rax, r11
+ adc r10, r12
+ mov QWORD PTR [rcx+112], rax
+ mov QWORD PTR [rcx+120], r10
+ pop r13
+ pop r12
+ ret
+sp_1024_mont_sub_avx2_16 ENDP
+_text ENDS
+ENDIF
+IFDEF HAVE_INTEL_AVX2
+; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
+; *
+; * r Result of division by 2.
+; * a Number to divide.
+; * m Modulus (prime).
+; */
+_text SEGMENT READONLY PARA
+sp_1024_div2_avx2_16 PROC
+ push r12
+ push r13
+ mov r13, QWORD PTR [rdx]
+ xor r12, r12
+ mov r10, r13
+ and r13, 1
+ neg r13
+ mov rax, QWORD PTR [r8]
+ mov r9, QWORD PTR [r8+8]
+ mov r10, QWORD PTR [rdx]
+ mov r11, QWORD PTR [rdx+8]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ add r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx], r10
+ mov QWORD PTR [rcx+8], r11
+ mov rax, QWORD PTR [r8+16]
+ mov r9, QWORD PTR [r8+24]
+ mov r10, QWORD PTR [rdx+16]
+ mov r11, QWORD PTR [rdx+24]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+16], r10
+ mov QWORD PTR [rcx+24], r11
+ mov rax, QWORD PTR [r8+32]
+ mov r9, QWORD PTR [r8+40]
+ mov r10, QWORD PTR [rdx+32]
+ mov r11, QWORD PTR [rdx+40]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+32], r10
+ mov QWORD PTR [rcx+40], r11
+ mov rax, QWORD PTR [r8+48]
+ mov r9, QWORD PTR [r8+56]
+ mov r10, QWORD PTR [rdx+48]
+ mov r11, QWORD PTR [rdx+56]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+48], r10
+ mov QWORD PTR [rcx+56], r11
+ mov rax, QWORD PTR [r8+64]
+ mov r9, QWORD PTR [r8+72]
+ mov r10, QWORD PTR [rdx+64]
+ mov r11, QWORD PTR [rdx+72]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+64], r10
+ mov QWORD PTR [rcx+72], r11
+ mov rax, QWORD PTR [r8+80]
+ mov r9, QWORD PTR [r8+88]
+ mov r10, QWORD PTR [rdx+80]
+ mov r11, QWORD PTR [rdx+88]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+80], r10
+ mov QWORD PTR [rcx+88], r11
+ mov rax, QWORD PTR [r8+96]
+ mov r9, QWORD PTR [r8+104]
+ mov r10, QWORD PTR [rdx+96]
+ mov r11, QWORD PTR [rdx+104]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+96], r10
+ mov QWORD PTR [rcx+104], r11
+ mov rax, QWORD PTR [r8+112]
+ mov r9, QWORD PTR [r8+120]
+ mov r10, QWORD PTR [rdx+112]
+ mov r11, QWORD PTR [rdx+120]
+ pext rax, rax, r13
+ pext r9, r9, r13
+ adc r10, rax
+ adc r11, r9
+ mov QWORD PTR [rcx+112], r10
+ mov QWORD PTR [rcx+120], r11
+ adc r12, 0
+ mov r10, QWORD PTR [rcx]
+ mov r11, QWORD PTR [rcx+8]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx], r10
+ mov r10, QWORD PTR [rcx+16]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+8], r11
+ mov r11, QWORD PTR [rcx+24]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+16], r10
+ mov r10, QWORD PTR [rcx+32]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+24], r11
+ mov r11, QWORD PTR [rcx+40]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+32], r10
+ mov r10, QWORD PTR [rcx+48]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+40], r11
+ mov r11, QWORD PTR [rcx+56]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+48], r10
+ mov r10, QWORD PTR [rcx+64]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+56], r11
+ mov r11, QWORD PTR [rcx+72]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+64], r10
+ mov r10, QWORD PTR [rcx+80]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+72], r11
+ mov r11, QWORD PTR [rcx+88]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+80], r10
+ mov r10, QWORD PTR [rcx+96]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+88], r11
+ mov r11, QWORD PTR [rcx+104]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+96], r10
+ mov r10, QWORD PTR [rcx+112]
+ shrd r11, r10, 1
+ mov QWORD PTR [rcx+104], r11
+ mov r11, QWORD PTR [rcx+120]
+ shrd r10, r11, 1
+ mov QWORD PTR [rcx+112], r10
+ shrd r11, r12, 1
+ mov QWORD PTR [rcx+120], r11
+ pop r13
+ pop r12
+ ret
+sp_1024_div2_avx2_16 ENDP
+_text ENDS
+ENDIF
+; /* Read big endian unsigned byte array into r.
+; * Uses the bswap instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_from_bin_bswap PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 128
+ xor r13, r13
+ jmp L_1024_from_bin_bswap_64_end
+L_1024_from_bin_bswap_64_start:
+ sub r11, 64
+ mov rax, QWORD PTR [r11+56]
+ mov r10, QWORD PTR [r11+48]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ mov rax, QWORD PTR [r11+40]
+ mov r10, QWORD PTR [r11+32]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ mov rax, QWORD PTR [r11+24]
+ mov r10, QWORD PTR [r11+16]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ mov rax, QWORD PTR [r11+8]
+ mov r10, QWORD PTR [r11]
+ bswap rax
+ bswap r10
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_1024_from_bin_bswap_64_end:
+ cmp r9, 63
+ jg L_1024_from_bin_bswap_64_start
+ jmp L_1024_from_bin_bswap_8_end
+L_1024_from_bin_bswap_8_start:
+ sub r11, 8
+ mov rax, QWORD PTR [r11]
+ bswap rax
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_1024_from_bin_bswap_8_end:
+ cmp r9, 7
+ jg L_1024_from_bin_bswap_8_start
+ cmp r9, r13
+ je L_1024_from_bin_bswap_hi_end
+ mov r10, r13
+ mov rax, r13
+L_1024_from_bin_bswap_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_1024_from_bin_bswap_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_1024_from_bin_bswap_hi_end:
+ cmp rcx, r12
+ je L_1024_from_bin_bswap_zero_end
+L_1024_from_bin_bswap_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_1024_from_bin_bswap_zero_start
+L_1024_from_bin_bswap_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_1024_from_bin_bswap ENDP
+_text ENDS
+IFNDEF NO_MOVBE_SUPPORT
+; /* Read big endian unsigned byte array into r.
+; * Uses the movbe instruction which is an optional instruction.
+; *
+; * r A single precision integer.
+; * size Maximum number of bytes to convert
+; * a Byte array.
+; * n Number of bytes in array to read.
+; */
+_text SEGMENT READONLY PARA
+sp_1024_from_bin_movbe PROC
+ push r12
+ push r13
+ mov r11, r8
+ mov r12, rcx
+ add r11, r9
+ add r12, 128
+ xor r13, r13
+ jmp L_1024_from_bin_movbe_64_end
+L_1024_from_bin_movbe_64_start:
+ sub r11, 64
+ movbe rax, QWORD PTR [r11+56]
+ movbe r10, QWORD PTR [r11+48]
+ mov QWORD PTR [rcx], rax
+ mov QWORD PTR [rcx+8], r10
+ movbe rax, QWORD PTR [r11+40]
+ movbe r10, QWORD PTR [r11+32]
+ mov QWORD PTR [rcx+16], rax
+ mov QWORD PTR [rcx+24], r10
+ movbe rax, QWORD PTR [r11+24]
+ movbe r10, QWORD PTR [r11+16]
+ mov QWORD PTR [rcx+32], rax
+ mov QWORD PTR [rcx+40], r10
+ movbe rax, QWORD PTR [r11+8]
+ movbe r10, QWORD PTR [r11]
+ mov QWORD PTR [rcx+48], rax
+ mov QWORD PTR [rcx+56], r10
+ add rcx, 64
+ sub r9, 64
+L_1024_from_bin_movbe_64_end:
+ cmp r9, 63
+ jg L_1024_from_bin_movbe_64_start
+ jmp L_1024_from_bin_movbe_8_end
+L_1024_from_bin_movbe_8_start:
+ sub r11, 8
+ movbe rax, QWORD PTR [r11]
+ mov QWORD PTR [rcx], rax
+ add rcx, 8
+ sub r9, 8
+L_1024_from_bin_movbe_8_end:
+ cmp r9, 7
+ jg L_1024_from_bin_movbe_8_start
+ cmp r9, r13
+ je L_1024_from_bin_movbe_hi_end
+ mov r10, r13
+ mov rax, r13
+L_1024_from_bin_movbe_hi_start:
+ mov al, BYTE PTR [r8]
+ shl r10, 8
+ inc r8
+ add r10, rax
+ dec r9
+ jg L_1024_from_bin_movbe_hi_start
+ mov QWORD PTR [rcx], r10
+ add rcx, 8
+L_1024_from_bin_movbe_hi_end:
+ cmp rcx, r12
+ je L_1024_from_bin_movbe_zero_end
+L_1024_from_bin_movbe_zero_start:
+ mov QWORD PTR [rcx], r13
+ add rcx, 8
+ cmp rcx, r12
+ jl L_1024_from_bin_movbe_zero_start
+L_1024_from_bin_movbe_zero_end:
+ pop r13
+ pop r12
+ ret
+sp_1024_from_bin_movbe ENDP
+_text ENDS
+ENDIF
+ENDIF
+END
diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c
index 4352567cc..9e29cab4c 100644
--- a/wolfcrypt/src/tfm.c
+++ b/wolfcrypt/src/tfm.c
@@ -1468,12 +1468,15 @@ int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp)
fp_sub_d(b, 2, e);
/* Highest bit is always set. */
- for (i = fp_count_bits(e)-2, j = 1; i >= 0; i--, j++) {
+ j = 1;
+ for (i = fp_count_bits(e)-2; i >= 0; i--) {
if (!fp_is_bit_set(e, i) || j == CT_INV_MOD_PRE_CNT)
break;
+ j++;
}
fp_copy(&pre[j-1], t);
- for (j = 0; i >= 0; i--) {
+ j = 0;
+ for (; i >= 0; i--) {
int set = fp_is_bit_set(e, i);
if ((j == CT_INV_MOD_PRE_CNT) || (!set && j > 0)) {
@@ -3660,10 +3663,11 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c)
int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b)
{
#if DIGIT_BIT == 64 || DIGIT_BIT == 32
- int i, j;
+ int i;
+ int j = 0;
fp_digit n;
- for (j=0,i=0; i