summary refs log tree commit diff stats
path: root/libotr/libgcrypt-1.8.7/mpi/generic
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libgcrypt-1.8.7/mpi/generic')
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/distfiles10
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpi-asm-defs.h8
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-add1.c65
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-lshift.c68
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul1.c62
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul2.c68
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul3.c68
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-rshift.c67
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/mpih-sub1.c66
-rw-r--r--libotr/libgcrypt-1.8.7/mpi/generic/udiv-w-sdiv.c133
10 files changed, 615 insertions, 0 deletions
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/distfiles b/libotr/libgcrypt-1.8.7/mpi/generic/distfiles
new file mode 100644
index 0000000..649e829
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/distfiles
@@ -0,0 +1,10 @@
+mpih-add1.c
+mpih-mul1.c
+mpih-mul2.c
+mpih-mul3.c
+mpih-lshift.c
+mpih-rshift.c
+mpih-sub1.c
+udiv-w-sdiv.c
+mpi-asm-defs.h
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpi-asm-defs.h b/libotr/libgcrypt-1.8.7/mpi/generic/mpi-asm-defs.h
new file mode 100644
index 0000000..e607806
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpi-asm-defs.h
@@ -0,0 +1,8 @@
+/* This file defines some basic constants for the MPI machinery.
+ * AMD64 compiled for the x32 ABI is special and thus we can't use the
+ * standard values for this ABI.  */
+#if __GNUC__ >= 3 && defined(__x86_64__) && defined(__ILP32__)
+#define BYTES_PER_MPI_LIMB 8
+#else
+#define BYTES_PER_MPI_LIMB  (SIZEOF_UNSIGNED_LONG)
+#endif
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-add1.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-add1.c
new file mode 100644
index 0000000..4a84df6
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-add1.c
@@ -0,0 +1,65 @@
+/* mpihelp-add_1.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 
+ *               2000, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+_gcry_mpih_add_n (mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                  mpi_ptr_t s2_ptr, mpi_size_t size)
+{
+  mpi_limb_t x, y, cy;
+  mpi_size_t j;
+
+  /* The loop counter and index J goes from -SIZE to -1.  This way
+     the loop becomes faster.  */
+  j = -size;
+
+  /* Offset the base pointers to compensate for the negative indices. */
+  s1_ptr -= j;
+  s2_ptr -= j;
+  res_ptr -= j;
+
+  cy = 0;
+  do 
+    {
+      y = s2_ptr[j];
+      x = s1_ptr[j];
+      y += cy;		  /* add previous carry to one addend */
+      cy = y < cy;	  /* get out carry from that addition */
+      y += x; 		  /* add other addend */
+      cy += y < x;	  /* get out carry from that add, combine */
+      res_ptr[j] = y;
+    } 
+  while ( ++j );
+
+  return cy;
+}
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-lshift.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-lshift.c
new file mode 100644
index 0000000..f48c12c
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-lshift.c
@@ -0,0 +1,68 @@
+/* mpi-lshift.c  - MPI helper functions
+ * Copyright (C) 1994, 1996, 1998, 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+
+/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
+ * and store the USIZE least significant digits of the result at WP.
+ * Return the bits shifted out from the most significant digit.
+ *
+ * Argument constraints:
+ * 1. 0 < CNT < BITS_PER_MP_LIMB
+ * 2. If the result is to be written over the input, WP must be >= UP.
+ */
+
+mpi_limb_t
+_gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+					    unsigned int cnt)
+{
+  mpi_limb_t high_limb, low_limb;
+  unsigned sh_1, sh_2;
+  mpi_size_t i;
+  mpi_limb_t retval;
+
+  sh_1 = cnt;
+  wp += 1;
+  sh_2 = BITS_PER_MPI_LIMB - sh_1;
+  i = usize - 1;
+  low_limb = up[i];
+  retval = low_limb >> sh_2;
+  high_limb = low_limb;
+  while ( --i >= 0 ) 
+    {
+      low_limb = up[i];
+      wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
+      high_limb = low_limb;
+    }
+  wp[i] = high_limb << sh_1;
+
+  return retval;
+}
+
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul1.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul1.c
new file mode 100644
index 0000000..0e8197d
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul1.c
@@ -0,0 +1,62 @@
+/* mpihelp-mul_1.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001,
+ *               2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+_gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+						    mpi_limb_t s2_limb)
+{
+  mpi_limb_t cy_limb;
+  mpi_size_t j;
+  mpi_limb_t prod_high, prod_low;
+
+  /* The loop counter and index J goes from -S1_SIZE to -1.  This way
+   * the loop becomes faster.  */
+  j = -s1_size;
+
+  /* Offset the base pointers to compensate for the negative indices.  */
+  s1_ptr -= j;
+  res_ptr -= j;
+
+  cy_limb = 0;
+  do 
+    {
+      umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb );
+      prod_low += cy_limb;
+      cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+      res_ptr[j] = prod_low;
+    } 
+  while( ++j );
+
+  return cy_limb;
+}
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul2.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul2.c
new file mode 100644
index 0000000..3b75496
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul2.c
@@ -0,0 +1,68 @@
+/* mpih-mul2.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001,
+ *               2002  Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+mpi_limb_t
+_gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+		  mpi_size_t s1_size, mpi_limb_t s2_limb)
+{
+  mpi_limb_t cy_limb;
+  mpi_size_t j;
+  mpi_limb_t prod_high, prod_low;
+  mpi_limb_t x;
+
+  /* The loop counter and index J goes from -SIZE to -1.  This way
+   * the loop becomes faster.  */
+  j = -s1_size;
+  res_ptr -= j;
+  s1_ptr -= j;
+
+  cy_limb = 0;
+  do 
+    {
+      umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb );
+
+      prod_low += cy_limb;
+      cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+
+      x = res_ptr[j];
+      prod_low = x + prod_low;
+      cy_limb += prod_low < x?1:0;
+      res_ptr[j] = prod_low;
+    } 
+  while ( ++j );
+    
+  return cy_limb;
+}
+
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul3.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul3.c
new file mode 100644
index 0000000..5e84f94
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-mul3.c
@@ -0,0 +1,68 @@
+/* mpih-mul3.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001,
+ *               2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+mpi_limb_t
+_gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+		  mpi_size_t s1_size, mpi_limb_t s2_limb)
+{
+  mpi_limb_t cy_limb;
+  mpi_size_t j;
+  mpi_limb_t prod_high, prod_low;
+  mpi_limb_t x;
+
+  /* The loop counter and index J goes from -SIZE to -1.  This way
+   * the loop becomes faster.  */
+  j = -s1_size;
+  res_ptr -= j;
+  s1_ptr -= j;
+
+  cy_limb = 0;
+  do 
+    {
+      umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb);
+
+      prod_low += cy_limb;
+      cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+
+      x = res_ptr[j];
+      prod_low = x - prod_low;
+      cy_limb += prod_low > x?1:0;
+      res_ptr[j] = prod_low;
+    } 
+  while( ++j );
+
+  return cy_limb;
+}
+
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-rshift.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-rshift.c
new file mode 100644
index 0000000..e40794f
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-rshift.c
@@ -0,0 +1,67 @@
+/* mpih-rshift.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1998, 1999,
+ *               2000, 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+
+
+/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
+ * and store the USIZE least significant limbs of the result at WP.
+ * The bits shifted out to the right are returned.
+ *
+ * Argument constraints:
+ * 1. 0 < CNT < BITS_PER_MP_LIMB
+ * 2. If the result is to be written over the input, WP must be <= UP.
+ */
+
+mpi_limb_t
+_gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt)
+{
+  mpi_limb_t high_limb, low_limb;
+  unsigned sh_1, sh_2;
+  mpi_size_t i;
+  mpi_limb_t retval;
+
+  sh_1 = cnt;
+  wp -= 1;
+  sh_2 = BITS_PER_MPI_LIMB - sh_1;
+  high_limb = up[0];
+  retval = high_limb << sh_2;
+  low_limb = high_limb;
+  for (i=1; i < usize; i++)
+    {
+      high_limb = up[i];
+      wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
+      low_limb = high_limb;
+    }
+  wp[i] = low_limb >> sh_1;
+
+  return retval;
+}
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/mpih-sub1.c b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-sub1.c
new file mode 100644
index 0000000..e88821b
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/mpih-sub1.c
@@ -0,0 +1,66 @@
+/* mpihelp-add_2.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001,
+ *               2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *	 Actually it's the same code with only minor changes in the
+ *	 way the data is stored; this is to support the abstraction
+ *	 of an optional secure memory allocation which may be used
+ *	 to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+_gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+				  mpi_ptr_t s2_ptr, mpi_size_t size)
+{
+  mpi_limb_t x, y, cy;
+  mpi_size_t j;
+
+  /* The loop counter and index J goes from -SIZE to -1.  This way
+     the loop becomes faster.  */
+  j = -size;
+
+  /* Offset the base pointers to compensate for the negative indices.  */
+  s1_ptr -= j;
+  s2_ptr -= j;
+  res_ptr -= j;
+
+  cy = 0;
+  do 
+    {
+      y = s2_ptr[j];
+      x = s1_ptr[j];
+      y += cy;		  /* add previous carry to subtrahend */
+      cy = y < cy;		  /* get out carry from that addition */
+      y = x - y;		  /* main subtract */
+      cy += y > x;		  /* get out carry from the subtract, combine */
+      res_ptr[j] = y;
+    } 
+  while( ++j );
+
+  return cy;
+}
+
+
diff --git a/libotr/libgcrypt-1.8.7/mpi/generic/udiv-w-sdiv.c b/libotr/libgcrypt-1.8.7/mpi/generic/udiv-w-sdiv.c
new file mode 100644
index 0000000..e80d98b
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/mpi/generic/udiv-w-sdiv.c
@@ -0,0 +1,133 @@
+/* mpih-w-sdiv -- implement udiv_qrnnd on machines with only signed
+ *	      	  division.
+ * Copyright (C) 1992, 1994, 1996, 1998, 2002 Free Software Foundation, Inc.
+ * Contributed by Peter L. Montgomery.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+#if 0  /* not yet ported to MPI */
+
+mpi_limb_t
+mpihelp_udiv_w_sdiv( mpi_limp_t *rp,
+		     mpi_limp_t *a1,
+		     mpi_limp_t *a0,
+		     mpi_limp_t *d   )
+{
+  mp_limb_t q, r;
+  mp_limb_t c0, c1, b1;
+
+  if ((mpi_limb_signed_t) d >= 0)
+    {
+      if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1)))
+	{
+	  /* dividend, divisor, and quotient are nonnegative */
+	  sdiv_qrnnd (q, r, a1, a0, d);
+	}
+      else
+	{
+	  /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+	  sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1));
+	  /* Divide (c1*2^32 + c0) by d */
+	  sdiv_qrnnd (q, r, c1, c0, d);
+	  /* Add 2^31 to quotient */
+	  q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+	}
+    }
+  else
+    {
+      b1 = d >> 1;			/* d/2, between 2^30 and 2^31 - 1 */
+      c1 = a1 >> 1;			/* A/2 */
+      c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1);
+
+      if (a1 < b1)			/* A < 2^32*b1, so A/2 < 2^31*b1 */
+	{
+	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+	  r = 2*r + (a0 & 1);		/* Remainder from A/(2*b1) */
+	  if ((d & 1) != 0)
+	    {
+	      if (r >= q)
+		r = r - q;
+	      else if (q - r <= d)
+		{
+		  r = r - q + d;
+		  q--;
+		}
+	      else
+		{
+		  r = r - q + 2*d;
+		  q -= 2;
+		}
+	    }
+	}
+      else if (c1 < b1) 		/* So 2^31 <= (A/2)/b1 < 2^32 */
+	{
+	  c1 = (b1 - 1) - c1;
+	  c0 = ~c0;			/* logical NOT */
+
+	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+	  q = ~q;			/* (A/2)/b1 */
+	  r = (b1 - 1) - r;
+
+	  r = 2*r + (a0 & 1);		/* A/(2*b1) */
+
+	  if ((d & 1) != 0)
+	    {
+	      if (r >= q)
+		r = r - q;
+	      else if (q - r <= d)
+		{
+		  r = r - q + d;
+		  q--;
+		}
+	      else
+		{
+		  r = r - q + 2*d;
+		  q -= 2;
+		}
+	    }
+	}
+      else				/* Implies c1 = b1 */
+	{				/* Hence a1 = d - 1 = 2*b1 - 1 */
+	  if (a0 >= -d)
+	    {
+	      q = -1;
+	      r = a0 + d;
+	    }
+	  else
+	    {
+	      q = -2;
+	      r = a0 + 2*d;
+	    }
+	}
+    }
+
+  *rp = r;
+  return q;
+}
+
+#endif
+