diff --git a/SHARED-FILES b/SHARED-FILES
index 8ea383b370..0c85e2e1b5 100644
--- a/SHARED-FILES
+++ b/SHARED-FILES
@@ -244,3 +244,7 @@ sysdeps/ieee754/flt-32/s_exp10m1f.c
   (file src/binary32/exp10m1/exp10m1f.c in CORE-MATH)
   - The code was adapted to use glibc code style and internal
     functions to handle errno, overflow, and underflow.
+sysdeps/ieee754/flt-32/s_exp2m1f.c
+  (file src/binary32/exp2m1/exp2m1f.c in CORE-MATH)
+  - The code was adapted to use glibc code style and internal
+    functions to handle errno, overflow, and underflow.
diff --git a/sysdeps/aarch64/libm-test-ulps b/sysdeps/aarch64/libm-test-ulps
index 00832393f6..29ccd1dfe9 100644
--- a/sysdeps/aarch64/libm-test-ulps
+++ b/sysdeps/aarch64/libm-test-ulps
@@ -1127,22 +1127,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_advsimd":
diff --git a/sysdeps/arc/fpu/libm-test-ulps b/sysdeps/arc/fpu/libm-test-ulps
index 4a8ad5142c..a5f9d50c39 100644
--- a/sysdeps/arc/fpu/libm-test-ulps
+++ b/sysdeps/arc/fpu/libm-test-ulps
@@ -815,19 +815,15 @@ float: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 
 Function: "exp_downward":
 double: 1
diff --git a/sysdeps/arc/nofpu/libm-test-ulps b/sysdeps/arc/nofpu/libm-test-ulps
index 4cecea6919..574ae8b8be 100644
--- a/sysdeps/arc/nofpu/libm-test-ulps
+++ b/sysdeps/arc/nofpu/libm-test-ulps
@@ -200,7 +200,6 @@ double: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 
 Function: "expm1":
 double: 1
diff --git a/sysdeps/arm/libm-test-ulps b/sysdeps/arm/libm-test-ulps
index bcbe82ca34..28718c7d2c 100644
--- a/sysdeps/arm/libm-test-ulps
+++ b/sysdeps/arm/libm-test-ulps
@@ -807,19 +807,15 @@ float: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 
 Function: "exp_downward":
 double: 1
diff --git a/sysdeps/hppa/fpu/libm-test-ulps b/sysdeps/hppa/fpu/libm-test-ulps
index 3dc1f2f8c3..338ca77ade 100644
--- a/sysdeps/hppa/fpu/libm-test-ulps
+++ b/sysdeps/hppa/fpu/libm-test-ulps
@@ -826,19 +826,15 @@ float: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 
 Function: "exp_downward":
 double: 1
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 96d02334e4..98a5a538ff 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -1194,25 +1194,21 @@ ldouble: 1
 
 Function: "exp2m1":
 double: 2
-float: 1
 float128: 2
 ldouble: 3
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 float128: 3
 ldouble: 6
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 float128: 4
 ldouble: 5
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 float128: 5
 ldouble: 6
 
diff --git a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps
index c18e2bc8de..9afb63bc0f 100644
--- a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps
+++ b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps
@@ -1197,25 +1197,21 @@ ldouble: 1
 
 Function: "exp2m1":
 double: 2
-float: 1
 float128: 2
 ldouble: 3
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 float128: 3
 ldouble: 6
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 float128: 4
 ldouble: 6
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 float128: 5
 ldouble: 6
 
diff --git a/sysdeps/ieee754/flt-32/s_exp2m1f.c b/sysdeps/ieee754/flt-32/s_exp2m1f.c
new file mode 100644
index 0000000000..f899152d2a
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_exp2m1f.c
@@ -0,0 +1,192 @@
+/* Correctly-rounded base-2 exponent function biased by 1 for binary32 value.
+
+Copyright (c) 2022-2024 Alexei Sibidanov.
+
+The original version of this file was copied from the CORE-MATH
+project (file src/binary32/exp2m1/exp2m1f.c, revision bc385c2).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <fenv.h>
+#include <math.h>
+#include "math_config.h"
+#include <libm-alias-float.h>
+#include <math-narrow-eval.h>
+#include <float.h>
+
+float
+__exp2m1f (float x)
+{
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_unlikely (ux >= 0xc1c80000u))
+    { /* x <= -25 */
+      if (ax > (0xffu << 23))
+	return x + x; /* nan */
+      return (ux == 0xff800000) ? -0x1p+0 : -0x1p+0 + 0x1p-26f;
+    }
+  else if (__glibc_unlikely (ax >= 0x43000000u))
+    { /* x >= 128 */
+      if (ax >= asuint (INFINITY))
+	return x + x; /* +Inf or NaN */
+      /* exp2m1 (MAX_EXP) should not overflow when rounding towards zero
+         or towards -Inf.  We round FLT_MAX + 2^103 which is in the middle
+         between FLT_MAX and 2^128 (the next number with unbounded range).  */
+      float ret = math_narrow_eval (FLT_MAX + 0x1p103f);
+      if (x == FLT_MAX_EXP && ret == FLT_MAX)
+        return ret;
+      return __math_oflowf (0);
+    }
+  else if (__glibc_unlikely (ax < 0x3df95f1fu))
+    { /* |x| < 8.44e-2/log(2) */
+      double z2 = z * z, r;
+      if (__glibc_unlikely (ax < 0x3d67a4ccu))
+	{ /* |x| < 3.92e-2/log(2) */
+	  if (__glibc_unlikely (ax < 0x3caa2feeu))
+	    { /* |x| < 1.44e-2/log(2) */
+	      if (__glibc_unlikely (ax < 0x3bac1405u))
+		{ /* |x| < 3.64e-3/log(2) */
+		  if (__glibc_unlikely (ax < 0x3a358876u))
+		    { /* |x| < 4.8e-4/log(2) */
+		      if (__glibc_unlikely (ax < 0x37d32ef6u))
+			{ /* |x| < 1.745e-5/log(2) */
+			  if (__glibc_unlikely (ax < 0x331fdd82u))
+			    { /* |x| < 2.58e-8/log(2) */
+			      if (__glibc_unlikely (ax < 0x2538aa3bu))
+				/* |x| < 1.60171e-16 */
+				r = 0x1.62e42fefa39efp-1;
+			      else
+				r = 0x1.62e42fefa39fp-1
+				  + z * 0x1.ebfbdff82c58fp-3;
+			    }
+			  else
+			    {
+			      if (__glibc_unlikely (ux == 0xb3d85005u))
+				return -0x1.2bdf76p-24 - 0x1.8p-77;
+			      if (__glibc_unlikely (ux == 0x3338428du))
+				return 0x1.fee08ap-26 + 0x1p-80;
+			      static const double c[] =
+				{
+				  0x1.62e42fefa39efp-1, 0x1.ebfbdff8548fdp-3,
+				  0x1.c6b08d704a06dp-5
+				};
+			      r = c[0] + z * (c[1] + z * c[2]);
+			    }
+			}
+		      else
+			{
+			  if (__glibc_unlikely (ux == 0x388bca4fu))
+			    return 0x1.839702p-15 - 0x1.8p-68;
+			  static const double c[] =
+			    {
+			      0x1.62e42fefa39efp-1, 0x1.ebfbdff82c58fp-3,
+			      0x1.c6b08dc82b347p-5, 0x1.3b2ab6fbad172p-7
+			    };
+			  r = (c[0] + z * c[1]) + z2 * (c[2] + z * c[3]);
+			}
+		    }
+		  else
+		    {
+		      static const double c[] =
+			{
+			  0x1.62e42fefa39efp-1, 0x1.ebfbdff82c068p-3,
+			  0x1.c6b08d704a6dcp-5, 0x1.3b2ac262c3eedp-7,
+			  0x1.5d87fe7af779ap-10
+			};
+		      r = (c[0] + z * c[1])
+			  + z2 * (c[2] + z * (c[3] + z * c[4]));
+		    }
+		}
+	      else
+		{
+		  static const double c[] =
+		    {
+		      0x1.62e42fefa39fp-1,   0x1.ebfbdff82c58dp-3,
+		      0x1.c6b08d7011d13p-5,  0x1.3b2ab6fbd267dp-7,
+		      0x1.5d88a81cea49ep-10, 0x1.430912ea9b963p-13
+		    };
+		  r = (c[0] + z * c[1])
+		      + z2 * ((c[2] + z * c[3]) + z2 * (c[4] + z * c[5]));
+		}
+	    }
+	  else
+	    {
+	      static const double c[] =
+		{
+		  0x1.62e42fefa39efp-1,  0x1.ebfbdff82c639p-3,
+		  0x1.c6b08d7049f1cp-5,  0x1.3b2ab6f5243bdp-7,
+		  0x1.5d87fe80a9e6cp-10, 0x1.430d0b9257fa8p-13,
+		  0x1.ffcbfc4cf0952p-17
+		};
+	      r = (c[0] + z * c[1])
+		  + z2 * ((c[2] + z * c[3])
+			  + z2 * (c[4] + z * (c[5] + z * c[6])));
+	    }
+	}
+      else
+	{
+	  static const double c[] =
+	    {
+	      0x1.62e42fefa39efp-1,  0x1.ebfbdff82c591p-3,
+	      0x1.c6b08d704cf6bp-5,  0x1.3b2ab6fba00cep-7,
+	      0x1.5d87fdfdaadb4p-10, 0x1.4309137333066p-13,
+	      0x1.ffe5e90daf7ddp-17, 0x1.62c0220eed731p-20
+	    };
+	  r = ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3]))
+	      + (z2 * z2) * ((c[4] + z * c[5]) + z2 * (c[6] + z * c[7]));
+	}
+      r *= z;
+      return r;
+    }
+  else
+    {
+      static const double c[] =
+	{
+	  0x1.62e42fefa398bp-5,  0x1.ebfbdff84555ap-11,
+	  0x1.c6b08d4ad86d3p-17, 0x1.3b2ad1b1716a2p-23,
+	  0x1.5d7472718ce9dp-30, 0x1.4a1d7f457ac56p-37
+	};
+      static const double tb[] =
+	{
+	  0x1p+0,               0x1.0b5586cf9890fp+0,  0x1.172b83c7d517bp+0,
+	  0x1.2387a6e756238p+0, 0x1.306fe0a31b715p+0,  0x1.3dea64c123422p+0,
+	  0x1.4bfdad5362a27p+0, 0x1.5ab07dd485429p+0,  0x1.6a09e667f3bcdp+0,
+	  0x1.7a11473eb0187p+0, 0x1.8ace5422aa0dap+0,  0x1.9c49182a3f09p+0,
+	  0x1.ae89f995ad3adp+0, 0x1.c199bdd85529cp+0,  0x1.d5818dcfba487p+0,
+	  0x1.ea4afa2a490dap+0
+	};
+      double a = 16.0 * z;
+      double ia = floor (a);
+      double h = a - ia;
+      double h2 = h * h;
+      int64_t i = ia, j = i & 0xf, e = i - j;
+      e >>= 4;
+      double s = tb[j];
+      s *= asdouble ((e + 0x3ffull) << 52);
+      double c0 = c[0] + h * c[1];
+      double c2 = c[2] + h * c[3];
+      double c4 = c[4] + h * c[5];
+      c0 += h2 * (c2 + h2 * c4);
+      double w = s * h;
+      return (s - 1.0) + w * c0;
+    }
+}
+libm_alias_float (__exp2m1, exp2m1)
diff --git a/sysdeps/loongarch/lp64/libm-test-ulps b/sysdeps/loongarch/lp64/libm-test-ulps
index de7e526008..c6fc9fd4ed 100644
--- a/sysdeps/loongarch/lp64/libm-test-ulps
+++ b/sysdeps/loongarch/lp64/libm-test-ulps
@@ -1010,22 +1010,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_downward":
diff --git a/sysdeps/m68k/m680x0/fpu/libm-test-ulps b/sysdeps/m68k/m680x0/fpu/libm-test-ulps
index 96cd7b3fd5..7fef8942ae 100644
--- a/sysdeps/m68k/m680x0/fpu/libm-test-ulps
+++ b/sysdeps/m68k/m680x0/fpu/libm-test-ulps
@@ -903,19 +903,15 @@ double: 1
 
 Function: "exp2m1":
 double: 1
-float: 1
 
 Function: "exp2m1_downward":
 double: 2
-float: 1
 
 Function: "exp2m1_towardzero":
 double: 2
-float: 1
 
 Function: "exp2m1_upward":
 double: 1
-float: 1
 
 Function: "exp_upward":
 double: 1
diff --git a/sysdeps/mips/mips32/libm-test-ulps b/sysdeps/mips/mips32/libm-test-ulps
index 829da3ebf1..d8daca6326 100644
--- a/sysdeps/mips/mips32/libm-test-ulps
+++ b/sysdeps/mips/mips32/libm-test-ulps
@@ -807,19 +807,15 @@ float: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 
 Function: "exp_downward":
 double: 1
diff --git a/sysdeps/mips/mips64/libm-test-ulps b/sysdeps/mips/mips64/libm-test-ulps
index 5c7b050b11..39e94d5480 100644
--- a/sysdeps/mips/mips64/libm-test-ulps
+++ b/sysdeps/mips/mips64/libm-test-ulps
@@ -1014,22 +1014,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_downward":
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index 30ddbaf05f..dd25aaf94a 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -1227,25 +1227,21 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 float128: 2
 ldouble: 3
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 float128: 3
 ldouble: 7
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 float128: 4
 ldouble: 8
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 float128: 5
 ldouble: 9
 
diff --git a/sysdeps/powerpc/nofpu/libm-test-ulps b/sysdeps/powerpc/nofpu/libm-test-ulps
index e15e1f8fc0..1e5bae039b 100644
--- a/sysdeps/powerpc/nofpu/libm-test-ulps
+++ b/sysdeps/powerpc/nofpu/libm-test-ulps
@@ -1023,22 +1023,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 7
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 8
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 9
 
 Function: "exp_downward":
diff --git a/sysdeps/riscv/nofpu/libm-test-ulps b/sysdeps/riscv/nofpu/libm-test-ulps
index 2271e1ee6c..11f891988e 100644
--- a/sysdeps/riscv/nofpu/libm-test-ulps
+++ b/sysdeps/riscv/nofpu/libm-test-ulps
@@ -995,7 +995,6 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 1
-float: 1
 ldouble: 1
 
 Function: "exp_downward":
diff --git a/sysdeps/riscv/rvd/libm-test-ulps b/sysdeps/riscv/rvd/libm-test-ulps
index 0bc61bf3c8..7d303fcb6b 100644
--- a/sysdeps/riscv/rvd/libm-test-ulps
+++ b/sysdeps/riscv/rvd/libm-test-ulps
@@ -1010,22 +1010,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_downward":
diff --git a/sysdeps/s390/fpu/libm-test-ulps b/sysdeps/s390/fpu/libm-test-ulps
index 860479f3ff..aa7a94a2be 100644
--- a/sysdeps/s390/fpu/libm-test-ulps
+++ b/sysdeps/s390/fpu/libm-test-ulps
@@ -1011,22 +1011,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_downward":
diff --git a/sysdeps/sparc/fpu/libm-test-ulps b/sysdeps/sparc/fpu/libm-test-ulps
index 4d8064b543..e7b3da6f1c 100644
--- a/sysdeps/sparc/fpu/libm-test-ulps
+++ b/sysdeps/sparc/fpu/libm-test-ulps
@@ -1014,22 +1014,18 @@ ldouble: 2
 
 Function: "exp2m1":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 ldouble: 4
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 ldouble: 5
 
 Function: "exp_downward":
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 3f438c2090..71697e99e0 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -1495,25 +1495,21 @@ float: 1
 
 Function: "exp2m1":
 double: 2
-float: 2
 float128: 2
 ldouble: 3
 
 Function: "exp2m1_downward":
 double: 3
-float: 3
 float128: 3
 ldouble: 6
 
 Function: "exp2m1_towardzero":
 double: 3
-float: 2
 float128: 4
 ldouble: 5
 
 Function: "exp2m1_upward":
 double: 3
-float: 3
 float128: 5
 ldouble: 6