diff -Naurd mpfr-2.2.1-p2/VERSION mpfr-2.2.1-p3/VERSION
--- mpfr-2.2.1-p2/VERSION	2007-02-15 23:37:58.000000000 +0000
+++ mpfr-2.2.1-p3/VERSION	2007-02-15 23:40:49.000000000 +0000
@@ -1 +1 @@
-2.2.1-p2
+2.2.1-p3
diff -Naurd mpfr-2.2.1-p2/mpfr.h mpfr-2.2.1-p3/mpfr.h
--- mpfr-2.2.1-p2/mpfr.h	2007-02-15 23:37:58.000000000 +0000
+++ mpfr-2.2.1-p3/mpfr.h	2007-02-15 23:40:49.000000000 +0000
@@ -26,7 +26,7 @@
 #define MPFR_VERSION_MAJOR 2
 #define MPFR_VERSION_MINOR 2
 #define MPFR_VERSION_PATCHLEVEL 1
-#define MPFR_VERSION_STRING "2.2.1-p2"
+#define MPFR_VERSION_STRING "2.2.1-p3"
 
 /* Macros dealing with MPFR VERSION */
 #define MPFR_VERSION_NUM(a,b,c) (((a) << 16L) | ((b) << 8) | (c))
@@ -626,13 +626,13 @@
      _p->_mpfr_sign = 1;                   \
      _p->_mpfr_exp = __MPFR_EXP_ZERO;      \
      (void) (_r); 0; }) :                  \
-   mpfr_set_ui (_f,_u,_r))
+   mpfr_set_ui_2exp ((_f), (_u), 0, (_r)))
 #endif
 #undef mpfr_set_si
 #define mpfr_set_si(_f,_s,_r)              \
  (__builtin_constant_p (_s) && (_s) >= 0 ? \
    mpfr_set_ui ((_f), (_s), (_r)) :        \
-   mpfr_set_si ((_f), (_s), (_r)))
+   mpfr_set_si_2exp ((_f), (_s), 0, (_r)))
 #endif
 #endif
 
diff -Naurd mpfr-2.2.1-p2/set_si.c mpfr-2.2.1-p3/set_si.c
--- mpfr-2.2.1-p2/set_si.c	2006-11-29 09:49:47.000000000 +0000
+++ mpfr-2.2.1-p3/set_si.c	2007-02-15 23:40:22.000000000 +0000
@@ -19,62 +19,11 @@
 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 MA 02110-1301, USA. */
 
-#define MPFR_NEED_LONGLONG_H
 #include "mpfr-impl.h"
 
+#undef mpfr_set_si
 int
-(mpfr_set_si) (mpfr_ptr x, long i, mp_rnd_t rnd_mode)
+mpfr_set_si (mpfr_ptr x, long i, mp_rnd_t rnd_mode)
 {
-  int inex;
-  mp_size_t xn;
-  unsigned int cnt, nbits;
-  mp_limb_t ai, *xp;
-
-  MPFR_CLEAR_FLAGS(x);
-  if (i == 0)
-    {
-      MPFR_SET_ZERO(x);
-      MPFR_SET_POS(x);
-      MPFR_RET(0);
-    }
-
-  xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
-  ai = SAFE_ABS(unsigned long, i);
-  MPFR_ASSERTN(SAFE_ABS(unsigned long, i) == ai);
-  count_leading_zeros(cnt, ai);
-
-  xp = MPFR_MANT(x);
-  xp[xn] = ai << cnt;
-  /* don't forget to put zero in lower limbs */
-  MPN_ZERO(xp, xn);
-  /* set sign */
-  if (i < 0)
-    MPFR_SET_NEG(x);
-  else
-    MPFR_SET_POS(x);
-
-  nbits = BITS_PER_MP_LIMB - cnt;
-  MPFR_EXP (x) = nbits;  /* may be out-of-range, check range below */
-  inex = mpfr_check_range(x, 0, rnd_mode);
-  if (inex)
-    return inex; /* underflow or overflow */
-
-  /* round if MPFR_PREC(x) smaller than length of i */
-  if (MPFR_UNLIKELY(MPFR_PREC(x) < nbits))
-    {
-      int carry;
-
-      carry = mpfr_round_raw(xp+xn, xp+xn, nbits, (i < 0), MPFR_PREC(x),
-                             rnd_mode, &inex);
-      if (MPFR_UNLIKELY(carry))
-        {
-          /* nbits is the current exponent */
-          if (MPFR_UNLIKELY((mp_exp_t) nbits == __gmpfr_emax))
-            return mpfr_overflow(x, rnd_mode, (i < 0 ? -1 : 1));
-          MPFR_SET_EXP (x, nbits + 1);
-          xp[xn] = MPFR_LIMB_HIGHBIT;
-        }
-    }
-
-  MPFR_RET(inex);
+  return mpfr_set_si_2exp (x, i, 0, rnd_mode);
 }
diff -Naurd mpfr-2.2.1-p2/set_si_2exp.c mpfr-2.2.1-p3/set_si_2exp.c
--- mpfr-2.2.1-p2/set_si_2exp.c	2006-11-29 09:49:47.000000000 +0000
+++ mpfr-2.2.1-p3/set_si_2exp.c	2007-02-15 23:40:22.000000000 +0000
@@ -20,18 +20,54 @@
 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 MA 02110-1301, USA. */
 
+#define MPFR_NEED_LONGLONG_H
 #include "mpfr-impl.h"
 
 int
 mpfr_set_si_2exp (mpfr_ptr x, long i, mp_exp_t e, mp_rnd_t rnd_mode)
 {
-  int res;
-  MPFR_SAVE_EXPO_DECL (expo);
+  if (i == 0)
+    {
+      MPFR_SET_ZERO (x);
+      MPFR_SET_POS (x);
+      MPFR_RET (0);
+    }
+  else
+    {
+      mp_size_t xn;
+      unsigned int cnt, nbits;
+      mp_limb_t ai, *xp;
+      int inex = 0;
 
-  MPFR_SAVE_EXPO_MARK (expo);
-  res = mpfr_set_si (x, i, rnd_mode);
-  mpfr_mul_2si (x, x, e, rnd_mode); /* Should be exact */
-  MPFR_SAVE_EXPO_FREE (expo);
-  res = mpfr_check_range(x, res, rnd_mode);
-  return res;
+      /* FIXME: support int limbs (e.g. 16-bit limbs on 16-bit proc) */
+      ai = SAFE_ABS (unsigned long, i);
+      MPFR_ASSERTN (SAFE_ABS (unsigned long, i) == ai);
+
+      /* Position of the highest limb */
+      xn = (MPFR_PREC (x) - 1) / BITS_PER_MP_LIMB;
+      count_leading_zeros (cnt, ai);
+      MPFR_ASSERTD (cnt < BITS_PER_MP_LIMB);  /* OK since i != 0 */
+
+      xp = MPFR_MANT(x);
+      xp[xn] = ai << cnt;
+      /* Zero the xn lower limbs. */
+      MPN_ZERO(xp, xn);
+      MPFR_SET_SIGN (x, i < 0 ? MPFR_SIGN_NEG : MPFR_SIGN_POS);
+
+      nbits = BITS_PER_MP_LIMB - cnt;
+      e += nbits;  /* exponent _before_ the rounding */
+
+      /* round if MPFR_PREC(x) smaller than length of i */
+      if (MPFR_UNLIKELY (MPFR_PREC (x) < nbits) &&
+          MPFR_UNLIKELY (mpfr_round_raw (xp + xn, xp + xn, nbits, i < 0,
+                                         MPFR_PREC (x), rnd_mode, &inex)))
+        {
+          e++;
+          xp[xn] = MPFR_LIMB_HIGHBIT;
+        }
+
+      MPFR_CLEAR_FLAGS (x);
+      MPFR_EXP (x) = e;
+      return mpfr_check_range (x, inex, rnd_mode);
+    }
 }
diff -Naurd mpfr-2.2.1-p2/set_ui.c mpfr-2.2.1-p3/set_ui.c
--- mpfr-2.2.1-p2/set_ui.c	2006-11-29 09:49:47.000000000 +0000
+++ mpfr-2.2.1-p3/set_ui.c	2007-02-15 23:40:21.000000000 +0000
@@ -19,60 +19,11 @@
 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 MA 02110-1301, USA. */
 
-#define MPFR_NEED_LONGLONG_H
 #include "mpfr-impl.h"
 
 #undef mpfr_set_ui
 int
 mpfr_set_ui (mpfr_ptr x, unsigned long i, mp_rnd_t rnd_mode)
 {
-  int inex;
-
-  MPFR_SET_POS(x);
-  if (i == 0)
-    {
-      MPFR_SET_ZERO(x);
-      MPFR_RET(0);
-    }
-  else
-    {
-      mp_size_t xn;
-      unsigned int cnt, nbits;
-      mp_limb_t *xp;
-
-      MPFR_CLEAR_FLAGS(x);
-
-      xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
-      MPFR_ASSERTD(i == (mp_limb_t) i);
-      count_leading_zeros(cnt, (mp_limb_t) i);
-
-      xp = MPFR_MANT(x);
-      xp[xn] = ((mp_limb_t) i) << cnt;
-      /* don't forget to put zero in lower limbs */
-      MPN_ZERO(xp, xn);
-
-      nbits = BITS_PER_MP_LIMB - cnt;
-      MPFR_EXP (x) = nbits;  /* may be out-of-range, check range below */
-      inex = mpfr_check_range(x, 0, rnd_mode);
-      if (inex)
-        return inex; /* underflow or overflow */
-
-      /* round if MPFR_PREC(x) smaller than length of i */
-      if (MPFR_UNLIKELY( MPFR_PREC(x) < nbits) )
-        {
-          int carry;
-          carry = mpfr_round_raw(xp+xn, xp+xn, nbits, 0, MPFR_PREC(x),
-                                 rnd_mode, &inex);
-          if (MPFR_UNLIKELY(carry))
-            {
-              /* nbits is the current exponent */
-              if (MPFR_UNLIKELY((mp_exp_t) nbits == __gmpfr_emax))
-                return mpfr_overflow(x, rnd_mode, 1);
-
-              MPFR_SET_EXP (x, nbits + 1);
-              xp[xn] = MPFR_LIMB_HIGHBIT;
-            }
-        }
-    }
-  MPFR_RET(inex);
+  return mpfr_set_ui_2exp (x, i, 0, rnd_mode);
 }
diff -Naurd mpfr-2.2.1-p2/set_ui_2exp.c mpfr-2.2.1-p3/set_ui_2exp.c
--- mpfr-2.2.1-p2/set_ui_2exp.c	2006-11-29 09:49:47.000000000 +0000
+++ mpfr-2.2.1-p3/set_ui_2exp.c	2007-02-15 23:40:22.000000000 +0000
@@ -20,18 +20,53 @@
 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 MA 02110-1301, USA. */
 
+#define MPFR_NEED_LONGLONG_H
 #include "mpfr-impl.h"
 
 int
 mpfr_set_ui_2exp (mpfr_ptr x, unsigned long i, mp_exp_t e, mp_rnd_t rnd_mode)
 {
-  int res;
-  MPFR_SAVE_EXPO_DECL (expo);
+  MPFR_SET_POS (x);
 
-  MPFR_SAVE_EXPO_MARK (expo);
-  res = mpfr_set_ui (x, i, rnd_mode);
-  mpfr_mul_2si (x, x, e, rnd_mode); /* Should be exact */
-  MPFR_SAVE_EXPO_FREE (expo);
-  res = mpfr_check_range(x, res, rnd_mode);
-  return res;
+  if (i == 0)
+    {
+      MPFR_SET_ZERO (x);
+      MPFR_RET (0);
+    }
+  else
+    {
+      mp_size_t xn;
+      unsigned int cnt, nbits;
+      mp_limb_t *xp;
+      int inex = 0;
+
+      /* FIXME: support int limbs (e.g. 16-bit limbs on 16-bit proc) */
+      MPFR_ASSERTD (i == (mp_limb_t) i);
+
+      /* Position of the highest limb */
+      xn = (MPFR_PREC (x) - 1) / BITS_PER_MP_LIMB;
+      count_leading_zeros (cnt, (mp_limb_t) i);
+      MPFR_ASSERTD (cnt < BITS_PER_MP_LIMB);  /* OK since i != 0 */
+
+      xp = MPFR_MANT(x);
+      xp[xn] = ((mp_limb_t) i) << cnt;
+      /* Zero the xn lower limbs. */
+      MPN_ZERO(xp, xn);
+
+      nbits = BITS_PER_MP_LIMB - cnt;
+      e += nbits;  /* exponent _before_ the rounding */
+
+      /* round if MPFR_PREC(x) smaller than length of i */
+      if (MPFR_UNLIKELY (MPFR_PREC (x) < nbits) &&
+          MPFR_UNLIKELY (mpfr_round_raw (xp + xn, xp + xn, nbits, 0,
+                                         MPFR_PREC (x), rnd_mode, &inex)))
+        {
+          e++;
+          xp[xn] = MPFR_LIMB_HIGHBIT;
+        }
+
+      MPFR_CLEAR_FLAGS (x);
+      MPFR_EXP (x) = e;
+      return mpfr_check_range (x, inex, rnd_mode);
+    }
 }
diff -Naurd mpfr-2.2.1-p2/tests/tset_si.c mpfr-2.2.1-p3/tests/tset_si.c
--- mpfr-2.2.1-p2/tests/tset_si.c	2006-11-29 09:49:47.000000000 +0000
+++ mpfr-2.2.1-p3/tests/tset_si.c	2007-02-15 23:40:21.000000000 +0000
@@ -69,6 +69,27 @@
   if (mpfr_cmp_ui (x, 1<<13) || res <= 0)
     ERROR ("Prec 2 + ui_2exp");
 
+  mpfr_clear_flags ();
+  mpfr_set_ui_2exp (x, 17, MPFR_EMAX_MAX, GMP_RNDN);
+  if (!mpfr_inf_p (x) || MPFR_IS_NEG (x))
+    ERROR ("mpfr_set_ui_2exp and overflow (bad result)");
+  if (!mpfr_overflow_p ())
+    ERROR ("mpfr_set_ui_2exp and overflow (overflow flag not set)");
+
+  mpfr_clear_flags ();
+  mpfr_set_si_2exp (x, 17, MPFR_EMAX_MAX, GMP_RNDN);
+  if (!mpfr_inf_p (x) || MPFR_IS_NEG (x))
+    ERROR ("mpfr_set_si_2exp (pos) and overflow (bad result)");
+  if (!mpfr_overflow_p ())
+    ERROR ("mpfr_set_si_2exp (pos) and overflow (overflow flag not set)");
+
+  mpfr_clear_flags ();
+  mpfr_set_si_2exp (x, -17, MPFR_EMAX_MAX, GMP_RNDN);
+  if (!mpfr_inf_p (x) || MPFR_IS_POS (x))
+    ERROR ("mpfr_set_si_2exp (neg) and overflow (bad result)");
+  if (!mpfr_overflow_p ())
+    ERROR ("mpfr_set_si_2exp (neg) and overflow (overflow flag not set)");
+
   mpfr_clear (x);
 }
 
@@ -112,7 +133,8 @@
   unsigned long zl, dl;
   int inex;
   int r;
-  mp_exp_t emax;
+  mp_exp_t emin, emax;
+  int flag;
 
   tests_start_mpfr ();
 
@@ -350,6 +372,43 @@
       exit (1);
     }
 
+  emin = mpfr_get_emin ();
+  mpfr_set_prec (x, 2);
+
+  mpfr_set_emin (4);
+  mpfr_clear_flags ();
+  mpfr_set_ui (x, 7, GMP_RNDU);
+  flag = mpfr_underflow_p ();
+  mpfr_set_emin (emin);
+  if (mpfr_cmp_ui (x, 8) != 0)
+    {
+      printf ("Error for mpfr_set_ui (x, 7, GMP_RNDU), prec = 2, emin = 4\n");
+      exit (1);
+    }
+  if (flag)
+    {
+      printf ("mpfr_set_ui (x, 7, GMP_RNDU) should not underflow "
+              "with prec = 2, emin = 4\n");
+      exit (1);
+    }
+
+  mpfr_set_emin (4);
+  mpfr_clear_flags ();
+  mpfr_set_si (x, -7, GMP_RNDD);
+  flag = mpfr_underflow_p ();
+  mpfr_set_emin (emin);
+  if (mpfr_cmp_si (x, -8) != 0)
+    {
+      printf ("Error for mpfr_set_si (x, -7, GMP_RNDD), prec = 2, emin = 4\n");
+      exit (1);
+    }
+  if (flag)
+    {
+      printf ("mpfr_set_si (x, -7, GMP_RNDD) should not underflow "
+              "with prec = 2, emin = 4\n");
+      exit (1);
+    }
+
   mpfr_clear (x);
 
   test_2exp ();
diff -Naurd mpfr-2.2.1-p2/version.c mpfr-2.2.1-p3/version.c
--- mpfr-2.2.1-p2/version.c	2007-02-15 23:37:58.000000000 +0000
+++ mpfr-2.2.1-p3/version.c	2007-02-15 23:40:49.000000000 +0000
@@ -24,5 +24,5 @@
 const char *
 mpfr_get_version (void)
 {
-  return "2.2.1-p2";
+  return "2.2.1-p3";
 }
