bigint: Provide a fallback implementation for `bn_mul_mont`.

Provide an implementation of `bn_mul_mont` that works on all targets that
don't have an assembly language implementation.

Expand `prefixed_export!` to support prefixing functions defined in Rust.
Function definitions don't end with a semicolon so move the semicolon
insertion from `prefixed_item!` to its callers.

Unify the codepaths in `bigint` so that `bn_mul_mont` is always used.

(cherry picked from commit 81f4e8d07da3f2ccc57f69a91245b41e6d764a1c)
Test: builds
Change-Id: If2cb061684ee1a0831f186c2f4cee3f02c2a236b
diff --git a/patches/0001-bigint-Provide-a-fallback-implementation-for-bn_mul_.patch b/patches/0001-bigint-Provide-a-fallback-implementation-for-bn_mul_.patch
new file mode 100644
index 0000000..ba53731
--- /dev/null
+++ b/patches/0001-bigint-Provide-a-fallback-implementation-for-bn_mul_.patch
@@ -0,0 +1,283 @@
+From a26dbf3aa0c3f0c68c4ffcdf1670ec998d088c1e Mon Sep 17 00:00:00 2001
+From: Brian Smith <brian@briansmith.org>
+Date: Fri, 11 Nov 2022 14:32:45 -0800
+Subject: [PATCH 1/2] bigint: Provide a fallback implementation for
+ `bn_mul_mont`.
+
+Provide an implementation of `bn_mul_mont` that works on all targets that
+don't have an assembly language implementation.
+
+Expand `prefixed_export!` to support prefixing functions defined in Rust.
+Function definitions don't end with a semicolon so move the semicolon
+insertion from `prefixed_item!` to its callers.
+
+Unify the codepaths in `bigint` so that `bn_mul_mont` is always used.
+
+(cherry picked from commit 81f4e8d07da3f2ccc57f69a91245b41e6d764a1c)
+Test: builds
+Change-Id: If2cb061684ee1a0831f186c2f4cee3f02c2a236b
+---
+ src/arithmetic/bigint.rs                      | 70 ++-----------------
+ src/arithmetic/bigint/bn_mul_mont_fallback.rs | 51 ++++++++++++++
+ src/prefixed.rs                               | 28 ++++++--
+ 3 files changed, 77 insertions(+), 72 deletions(-)
+ create mode 100644 src/arithmetic/bigint/bn_mul_mont_fallback.rs
+
+diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs
+index 2b2cdf31f..1eb90fead 100644
+--- a/src/arithmetic/bigint.rs
++++ b/src/arithmetic/bigint.rs
+@@ -47,6 +47,8 @@ use core::{
+     ops::{Deref, DerefMut},
+ };
+ 
++mod bn_mul_mont_fallback;
++
+ pub unsafe trait Prime {}
+ 
+ struct Width<M> {
+@@ -1231,13 +1233,6 @@ impl From<u64> for N0 {
+ fn limbs_mont_mul(r: &mut [Limb], a: &[Limb], m: &[Limb], n0: &N0) {
+     debug_assert_eq!(r.len(), m.len());
+     debug_assert_eq!(a.len(), m.len());
+-
+-    #[cfg(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    ))]
+     unsafe {
+         bn_mul_mont(
+             r.as_mut_ptr(),
+@@ -1248,19 +1243,6 @@ fn limbs_mont_mul(r: &mut [Limb], a: &[Limb], m: &[Limb], n0: &N0) {
+             r.len(),
+         )
+     }
+-
+-    #[cfg(not(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    )))]
+-    {
+-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
+-        let tmp = &mut tmp[..(2 * a.len())];
+-        limbs_mul(tmp, r, a);
+-        limbs_from_mont_in_place(r, tmp, m, n0);
+-    }
+ }
+ 
+ fn limbs_from_mont_in_place(r: &mut [Limb], tmp: &mut [Limb], m: &[Limb], n0: &N0) {
+@@ -1292,8 +1274,8 @@ fn limbs_from_mont_in_place(r: &mut [Limb], tmp: &mut [Limb], m: &[Limb], n0: &N
+ #[cfg(not(any(
+     target_arch = "aarch64",
+     target_arch = "arm",
+-    target_arch = "x86_64",
+-    target_arch = "x86"
++    target_arch = "x86",
++    target_arch = "x86_64"
+ )))]
+ fn limbs_mul(r: &mut [Limb], a: &[Limb], b: &[Limb]) {
+     debug_assert_eq!(r.len(), 2 * a.len());
+@@ -1320,12 +1302,6 @@ fn limbs_mont_product(r: &mut [Limb], a: &[Limb], b: &[Limb], m: &[Limb], n0: &N
+     debug_assert_eq!(a.len(), m.len());
+     debug_assert_eq!(b.len(), m.len());
+ 
+-    #[cfg(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    ))]
+     unsafe {
+         bn_mul_mont(
+             r.as_mut_ptr(),
+@@ -1336,30 +1312,11 @@ fn limbs_mont_product(r: &mut [Limb], a: &[Limb], b: &[Limb], m: &[Limb], n0: &N
+             r.len(),
+         )
+     }
+-
+-    #[cfg(not(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    )))]
+-    {
+-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
+-        let tmp = &mut tmp[..(2 * a.len())];
+-        limbs_mul(tmp, a, b);
+-        limbs_from_mont_in_place(r, tmp, m, n0)
+-    }
+ }
+ 
+ /// r = r**2
+ fn limbs_mont_square(r: &mut [Limb], m: &[Limb], n0: &N0) {
+     debug_assert_eq!(r.len(), m.len());
+-    #[cfg(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    ))]
+     unsafe {
+         bn_mul_mont(
+             r.as_mut_ptr(),
+@@ -1370,27 +1327,8 @@ fn limbs_mont_square(r: &mut [Limb], m: &[Limb], n0: &N0) {
+             r.len(),
+         )
+     }
+-
+-    #[cfg(not(any(
+-        target_arch = "aarch64",
+-        target_arch = "arm",
+-        target_arch = "x86_64",
+-        target_arch = "x86"
+-    )))]
+-    {
+-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
+-        let tmp = &mut tmp[..(2 * r.len())];
+-        limbs_mul(tmp, r, r);
+-        limbs_from_mont_in_place(r, tmp, m, n0)
+-    }
+ }
+ 
+-#[cfg(any(
+-    target_arch = "aarch64",
+-    target_arch = "arm",
+-    target_arch = "x86_64",
+-    target_arch = "x86"
+-))]
+ prefixed_extern! {
+     // `r` and/or 'a' and/or 'b' may alias.
+     fn bn_mul_mont(
+diff --git a/src/arithmetic/bigint/bn_mul_mont_fallback.rs b/src/arithmetic/bigint/bn_mul_mont_fallback.rs
+new file mode 100644
+index 000000000..1357858d0
+--- /dev/null
++++ b/src/arithmetic/bigint/bn_mul_mont_fallback.rs
+@@ -0,0 +1,51 @@
++// Copyright 2015-2022 Brian Smith.
++//
++// Permission to use, copy, modify, and/or distribute this software for any
++// purpose with or without fee is hereby granted, provided that the above
++// copyright notice and this permission notice appear in all copies.
++//
++// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
++// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
++// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++
++#![cfg(not(any(
++    target_arch = "aarch64",
++    target_arch = "arm",
++    target_arch = "x86",
++    target_arch = "x86_64"
++)))]
++
++use super::{limbs_from_mont_in_place, limbs_mul, Limb, MODULUS_MAX_LIMBS, N0};
++use crate::c;
++
++prefixed_export! {
++    unsafe fn bn_mul_mont(
++        r: *mut Limb,
++        a: *const Limb,
++        b: *const Limb,
++        n: *const Limb,
++        n0: &N0,
++        num_limbs: c::size_t,
++    ) {
++        // The mutable pointer `r` may alias `a` and/or `b`, so the lifetimes of
++        // any slices for `a` or `b` must not overlap with the lifetime of any
++        // mutable for `r`.
++
++        // Nothing aliases `n`
++        let n = unsafe { core::slice::from_raw_parts(n, num_limbs) };
++
++        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
++        let tmp = &mut tmp[..(2 * num_limbs)];
++        {
++            let a: &[Limb] = unsafe { core::slice::from_raw_parts(a, num_limbs) };
++            let b: &[Limb] = unsafe { core::slice::from_raw_parts(b, num_limbs) };
++            limbs_mul(tmp, a, b);
++        }
++        let r: &mut [Limb] = unsafe { core::slice::from_raw_parts_mut(r, num_limbs) };
++        limbs_from_mont_in_place(r, tmp, n, n0);
++    }
++}
+diff --git a/src/prefixed.rs b/src/prefixed.rs
+index c8ac807ee..a35f9212f 100644
+--- a/src/prefixed.rs
++++ b/src/prefixed.rs
+@@ -14,7 +14,7 @@ macro_rules! prefixed_extern {
+                     $name
+                     {
+                         $( #[$meta] )*
+-                        $vis fn $name ( $( $arg_pat : $arg_ty ),* ) $( -> $ret_ty )?
++                        $vis fn $name ( $( $arg_pat : $arg_ty ),* ) $( -> $ret_ty )?;
+                     }
+ 
+                 }
+@@ -33,15 +33,31 @@ macro_rules! prefixed_extern {
+                 $name
+                 {
+                     $( #[$meta] )*
+-                    $vis static mut $name: $typ
++                    $vis static mut $name: $typ;
+                 }
+             }
+         }
+     };
+ }
+ 
+-#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
++#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+ macro_rules! prefixed_export {
++    // A function.
++    {
++        $( #[$meta:meta] )*
++        $vis:vis unsafe fn $name:ident ( $( $arg_pat:ident : $arg_ty:ty ),* $(,)? ) $body:block
++    } => {
++        prefixed_item! {
++            export_name
++            $name
++            {
++                $( #[$meta] )*
++                $vis unsafe fn $name ( $( $arg_pat : $arg_ty ),* ) $body
++            }
++        }
++    };
++
++    // A global variable.
+     {
+         $( #[$meta:meta] )*
+         $vis:vis static mut $name:ident: $typ:ty = $initial_value:expr;
+@@ -51,10 +67,10 @@ macro_rules! prefixed_export {
+             $name
+             {
+                 $( #[$meta] )*
+-                $vis static mut $name: $typ = $initial_value
++                $vis static mut $name: $typ = $initial_value;
+             }
+         }
+-    }
++    };
+ }
+ 
+ macro_rules! prefixed_item {
+@@ -81,6 +97,6 @@ macro_rules! prefixed_item {
+         { $( $item:tt )+ }
+     } => {
+         #[$attr = $prefixed_name]
+-        $( $item )+;
++        $( $item )+
+     };
+ }
+-- 
+2.39.1.519.gcb327c4b5f-goog
+
diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs
index 2b2cdf3..1eb90fe 100644
--- a/src/arithmetic/bigint.rs
+++ b/src/arithmetic/bigint.rs
@@ -47,6 +47,8 @@
     ops::{Deref, DerefMut},
 };
 
+mod bn_mul_mont_fallback;
+
 pub unsafe trait Prime {}
 
 struct Width<M> {
@@ -1231,13 +1233,6 @@
 fn limbs_mont_mul(r: &mut [Limb], a: &[Limb], m: &[Limb], n0: &N0) {
     debug_assert_eq!(r.len(), m.len());
     debug_assert_eq!(a.len(), m.len());
-
-    #[cfg(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    ))]
     unsafe {
         bn_mul_mont(
             r.as_mut_ptr(),
@@ -1248,19 +1243,6 @@
             r.len(),
         )
     }
-
-    #[cfg(not(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    )))]
-    {
-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
-        let tmp = &mut tmp[..(2 * a.len())];
-        limbs_mul(tmp, r, a);
-        limbs_from_mont_in_place(r, tmp, m, n0);
-    }
 }
 
 fn limbs_from_mont_in_place(r: &mut [Limb], tmp: &mut [Limb], m: &[Limb], n0: &N0) {
@@ -1292,8 +1274,8 @@
 #[cfg(not(any(
     target_arch = "aarch64",
     target_arch = "arm",
-    target_arch = "x86_64",
-    target_arch = "x86"
+    target_arch = "x86",
+    target_arch = "x86_64"
 )))]
 fn limbs_mul(r: &mut [Limb], a: &[Limb], b: &[Limb]) {
     debug_assert_eq!(r.len(), 2 * a.len());
@@ -1320,12 +1302,6 @@
     debug_assert_eq!(a.len(), m.len());
     debug_assert_eq!(b.len(), m.len());
 
-    #[cfg(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    ))]
     unsafe {
         bn_mul_mont(
             r.as_mut_ptr(),
@@ -1336,30 +1312,11 @@
             r.len(),
         )
     }
-
-    #[cfg(not(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    )))]
-    {
-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
-        let tmp = &mut tmp[..(2 * a.len())];
-        limbs_mul(tmp, a, b);
-        limbs_from_mont_in_place(r, tmp, m, n0)
-    }
 }
 
 /// r = r**2
 fn limbs_mont_square(r: &mut [Limb], m: &[Limb], n0: &N0) {
     debug_assert_eq!(r.len(), m.len());
-    #[cfg(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    ))]
     unsafe {
         bn_mul_mont(
             r.as_mut_ptr(),
@@ -1370,27 +1327,8 @@
             r.len(),
         )
     }
-
-    #[cfg(not(any(
-        target_arch = "aarch64",
-        target_arch = "arm",
-        target_arch = "x86_64",
-        target_arch = "x86"
-    )))]
-    {
-        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
-        let tmp = &mut tmp[..(2 * r.len())];
-        limbs_mul(tmp, r, r);
-        limbs_from_mont_in_place(r, tmp, m, n0)
-    }
 }
 
-#[cfg(any(
-    target_arch = "aarch64",
-    target_arch = "arm",
-    target_arch = "x86_64",
-    target_arch = "x86"
-))]
 prefixed_extern! {
     // `r` and/or 'a' and/or 'b' may alias.
     fn bn_mul_mont(
diff --git a/src/arithmetic/bigint/bn_mul_mont_fallback.rs b/src/arithmetic/bigint/bn_mul_mont_fallback.rs
new file mode 100644
index 0000000..1357858
--- /dev/null
+++ b/src/arithmetic/bigint/bn_mul_mont_fallback.rs
@@ -0,0 +1,51 @@
+// Copyright 2015-2022 Brian Smith.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#![cfg(not(any(
+    target_arch = "aarch64",
+    target_arch = "arm",
+    target_arch = "x86",
+    target_arch = "x86_64"
+)))]
+
+use super::{limbs_from_mont_in_place, limbs_mul, Limb, MODULUS_MAX_LIMBS, N0};
+use crate::c;
+
+prefixed_export! {
+    unsafe fn bn_mul_mont(
+        r: *mut Limb,
+        a: *const Limb,
+        b: *const Limb,
+        n: *const Limb,
+        n0: &N0,
+        num_limbs: c::size_t,
+    ) {
+        // The mutable pointer `r` may alias `a` and/or `b`, so the lifetimes of
+        // any slices for `a` or `b` must not overlap with the lifetime of any
+        // mutable for `r`.
+
+        // Nothing aliases `n`
+        let n = unsafe { core::slice::from_raw_parts(n, num_limbs) };
+
+        let mut tmp = [0; 2 * MODULUS_MAX_LIMBS];
+        let tmp = &mut tmp[..(2 * num_limbs)];
+        {
+            let a: &[Limb] = unsafe { core::slice::from_raw_parts(a, num_limbs) };
+            let b: &[Limb] = unsafe { core::slice::from_raw_parts(b, num_limbs) };
+            limbs_mul(tmp, a, b);
+        }
+        let r: &mut [Limb] = unsafe { core::slice::from_raw_parts_mut(r, num_limbs) };
+        limbs_from_mont_in_place(r, tmp, n, n0);
+    }
+}
diff --git a/src/prefixed.rs b/src/prefixed.rs
index c8ac807..a35f921 100644
--- a/src/prefixed.rs
+++ b/src/prefixed.rs
@@ -14,7 +14,7 @@
                     $name
                     {
                         $( #[$meta] )*
-                        $vis fn $name ( $( $arg_pat : $arg_ty ),* ) $( -> $ret_ty )?
+                        $vis fn $name ( $( $arg_pat : $arg_ty ),* ) $( -> $ret_ty )?;
                     }
 
                 }
@@ -33,15 +33,31 @@
                 $name
                 {
                     $( #[$meta] )*
-                    $vis static mut $name: $typ
+                    $vis static mut $name: $typ;
                 }
             }
         }
     };
 }
 
-#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 macro_rules! prefixed_export {
+    // A function.
+    {
+        $( #[$meta:meta] )*
+        $vis:vis unsafe fn $name:ident ( $( $arg_pat:ident : $arg_ty:ty ),* $(,)? ) $body:block
+    } => {
+        prefixed_item! {
+            export_name
+            $name
+            {
+                $( #[$meta] )*
+                $vis unsafe fn $name ( $( $arg_pat : $arg_ty ),* ) $body
+            }
+        }
+    };
+
+    // A global variable.
     {
         $( #[$meta:meta] )*
         $vis:vis static mut $name:ident: $typ:ty = $initial_value:expr;
@@ -51,10 +67,10 @@
             $name
             {
                 $( #[$meta] )*
-                $vis static mut $name: $typ = $initial_value
+                $vis static mut $name: $typ = $initial_value;
             }
         }
-    }
+    };
 }
 
 macro_rules! prefixed_item {
@@ -81,6 +97,6 @@
         { $( $item:tt )+ }
     } => {
         #[$attr = $prefixed_name]
-        $( $item )+;
+        $( $item )+
     };
 }