diff mbox

Refactor x86_64 libm code forcing underflow exceptions [committed]

Message ID alpine.DEB.2.10.1509242226110.5465@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Sept. 24, 2015, 10:26 p.m. UTC
This patch refactors code in sysdeps/x86_64/fpu that forces underflow
exceptions and closely follows corresponding i386 code to use common
macros in x86_64-math-asm.h for that purpose.  This is mainly about
keeping the code similar to the i386 code as far as possible, since
each macro apart from DEFINE_LDBL_MIN ends up used only once.  It
would be possible to do a further refactoring to share these macros
between i386 and x86_64 (with i386 using the fcomip / fucomip versions
when building for i686 and above), but I have no immediate plans to do
so.

Tested for x86_64.  Committed.

2015-09-24  Joseph Myers  <joseph@codesourcery.com>

	* sysdeps/x86_64/fpu/x86_64-math-asm.h: New file.
	* sysdeps/x86_64/fpu/e_exp2l.S: Include <x86_64-math-asm.h>.
	(ldbl_min): Replace with use of DEFINE_LDBL_MIN.
	(__ieee754_exp2l): Use LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN.
	* sysdeps/x86_64/fpu/e_expl.S: Include <x86_64-math-asm.h>.
	[!USE_AS_EXPM1L] (cmin): Replace with use of DEFINE_LDBL_MIN.
	(IEEE754_EXPL): Use LDBL_CHECK_FORCE_UFLOW_NONNEG.
diff mbox

Patch

diff --git a/sysdeps/x86_64/fpu/e_exp2l.S b/sysdeps/x86_64/fpu/e_exp2l.S
index d634ad3..0e059b7 100644
--- a/sysdeps/x86_64/fpu/e_exp2l.S
+++ b/sysdeps/x86_64/fpu/e_exp2l.S
@@ -6,13 +6,9 @@ 
  */
 
 #include <machine/asm.h>
+#include <x86_64-math-asm.h>
 
-	.section .rodata.cst16,"aM",@progbits,16
-	.p2align 4
-	.type ldbl_min,@object
-ldbl_min:	.byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0
-	.byte 0, 0, 0, 0, 0, 0
-	ASM_SIZE_DIRECTIVE(ldbl_min)
+DEFINE_LDBL_MIN
 
 #ifdef PIC
 # define MO(op) op##(%rip)
@@ -50,16 +46,8 @@  ENTRY(__ieee754_exp2l)
 	faddp				/* 2^(fract(x)) */
 	fscale				/* e^x */
 	fstp	%st(1)
-	/* Ensure underflow for tiny result.  */
-	fldt	MO(ldbl_min)
-	fld	%st(1)
-	fucomip	%st(1), %st
-	fstp	%st
-	jnc	4f
-	fld	%st
-	fmul	%st
-	fstp	%st
-4:	ret
+	LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN
+	ret
 
 1:	testl	$0x200, %eax		/* Test sign.  */
 	jz	2f			/* If positive, jump.  */
diff --git a/sysdeps/x86_64/fpu/e_expl.S b/sysdeps/x86_64/fpu/e_expl.S
index 14dd29d..8b3ddae 100644
--- a/sysdeps/x86_64/fpu/e_expl.S
+++ b/sysdeps/x86_64/fpu/e_expl.S
@@ -23,6 +23,7 @@ 
  */
 
 #include <machine/asm.h>
+#include <x86_64-math-asm.h>
 
 #ifdef USE_AS_EXP10L
 # define IEEE754_EXPL __ieee754_exp10l
@@ -65,10 +66,7 @@  c1:	.byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
 csat:	.byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
 	.byte 0, 0, 0, 0, 0, 0
 	ASM_SIZE_DIRECTIVE(csat)
-	.type cmin,@object
-cmin:	.byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0
-	.byte 0, 0, 0, 0, 0, 0
-	ASM_SIZE_DIRECTIVE(cmin)
+DEFINE_LDBL_MIN
 #endif
 
 #ifdef PIC
@@ -192,17 +190,9 @@  ENTRY(IEEE754_EXPL)
 	fstp	%st(1)		/* 2  */
 	fscale			/* 2 scale factor is st(1); base^x */
 	fstp	%st(1)		/* 1  */
-	/* Ensure underflow for tiny result.  */
-	fldt	MO(cmin)	/* 2 cmin  */
-	fld	%st(1)		/* 3  */
-	fcomip	%st(1), %st	/* 2  */
-	fstp	%st		/* 1  */
-	jnc	6f
-	fld	%st
-	fmul	%st
-	fstp	%st
+	LDBL_CHECK_FORCE_UFLOW_NONNEG
 #endif
-6:	fstp	%st(1)		/* 0  */
+	fstp	%st(1)		/* 0  */
 	jmp	2f
 1:
 #ifdef USE_AS_EXPM1L
diff --git a/sysdeps/x86_64/fpu/x86_64-math-asm.h b/sysdeps/x86_64/fpu/x86_64-math-asm.h
new file mode 100644
index 0000000..07eecf7
--- /dev/null
+++ b/sysdeps/x86_64/fpu/x86_64-math-asm.h
@@ -0,0 +1,61 @@ 
+/* Helper macros for x86_64 libm functions.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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 the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _X86_64_MATH_ASM_H
+#define _X86_64_MATH_ASM_H 1
+
+/* Define constants for the minimum value of a floating-point
+   type.  */
+#define DEFINE_LDBL_MIN					\
+	.section .rodata.cst16,"aM",@progbits,16;	\
+	.p2align 4;					\
+	.type ldbl_min,@object;				\
+ldbl_min:						\
+	.byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0;	\
+	.byte 0, 0, 0, 0, 0, 0;				\
+	.size ldbl_min, .-ldbl_min;
+
+/* Force an underflow exception if the given value (nonnegative or
+   NaN) is subnormal.  The relevant constant for the minimum of the
+   type must have been defined, the MO macro must have been defined
+   for access to memory operands, and, if PIC, the PIC register must
+   have been loaded.  */
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN	\
+	fldt	MO(ldbl_min);			\
+	fld	%st(1);				\
+	fucomip	%st(1), %st(0);			\
+	fstp	%st(0);				\
+	jnc 6464f;				\
+	fld	%st(0);				\
+	fmul	%st(0);				\
+	fstp	%st(0);				\
+6464:
+
+/* Likewise, but the argument is nonnegative and not a NaN.  */
+#define LDBL_CHECK_FORCE_UFLOW_NONNEG		\
+	fldt	MO(ldbl_min);			\
+	fld	%st(1);				\
+	fcomip	%st(1), %st(0);			\
+	fstp	%st(0);				\
+	jnc 6464f;				\
+	fld	%st(0);				\
+	fmul	%st(0);				\
+	fstp	%st(0);				\
+6464:
+
+#endif /* x86_64-math-asm.h.  */