[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patches] DFP branch: S/390 DFP support
- To: patches@xxxxxxxxxx
- Subject: [patches] DFP branch: S/390 DFP support
- From: "Andreas Krebbel" <krebbel@xxxxxxxxxxxxxxxxxx>
- Date: Fri, 29 Aug 2008 16:25:26 +0200
Hello,
this is an updated version of the S/390 DFP support. I've added
support of the numdigits functions and have copied over the
implementation of the generic functions manipulating the exception
handling mask.
Please apply if you think it is ok.
Bye,
-Andreas-
2008-08-29 Andreas Krebbel <krebbel1@xxxxxxxxxx>
* dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/fpu/Implies: New file.
* dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/Implies: New file.
* dfp/sysdeps/s390/s390-64/z9-ec/fpu/Implies: New file.
* dfp/sysdeps/unix/sysv/linux/s390/Implies: New file.
* dfp/sysdeps/s390/dfpu/fe_decround.c: New file.
* dfp/sysdeps/s390/fpu/fraiseexcpt.c: Duplicate of bfp file.
* dfp/sysdeps/s390/fpu/ftestexcept.c: Likewise.
* dfp/sysdeps/s390/fpu/fclrexcpt.c: Likewise.
* dfp/sysdeps/s390/dfpu/fenv_libc.h: New file.
* dfp/sysdeps/s390/dfpu/fpu_control.h: New file.
* dfp/sysdeps/s390/dfpu/numdigits.h: New file.
* dfp/sysdeps/s390/fpu/Makefile: New file.
Index: dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/fpu/Implies
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/fpu/Implies 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1 @@
+s390/s390-64/z9-ec/fpu
Index: dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/Implies
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/unix/sysv/linux/s390/s390-64/z9-ec/Implies 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1 @@
+s390/dfpu
Index: dfp/sysdeps/s390/dfpu/fe_decround.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/dfpu/fe_decround.c 2008-08-29 16:07:20.000000000 +0200
@@ -0,0 +1,53 @@
+/* Return current rounding direction.
+ Copyright (C) 2000, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Krebbel <Andreas.Krebbel@xxxxxxxxxx>
+
+ Based on the binary floating point variants contributed
+ by Denis Joseph Barrow (djbarrow@xxxxxxxxxx).
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+__fe_dec_getround (void)
+{
+ fexcept_t cw;
+
+ _FPU_GETCW (cw);
+
+ return (cw & FPC_DFP_RM_MASK) >> 4;
+}
+strong_alias(__fe_dec_getround, fe_dec_getround)
+
+int
+__fe_dec_setround (int round)
+{
+ if ((round|FPC_DFP_RM_MASK) != FPC_DFP_RM_MASK
+ || (round > FE_DEC_TONEARESTFROMZERO))
+ {
+ /* ROUND is not a valid rounding mode. */
+ return 1;
+ }
+ __asm__ volatile ("srnmt 0(%0)"
+ :
+ : "a" (round << 4));
+
+ return 0;
+}
+strong_alias(__fe_dec_setround, fe_dec_setround)
Index: dfp/sysdeps/s390/dfpu/fenv_libc.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/dfpu/fenv_libc.h 2008-08-29 16:07:13.000000000 +0200
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Krebbel <Andreas.Krebbel@xxxxxxxxxx>
+
+ Based on the binary floating point variants contributed
+ by Denis Joseph Barrow (djbarrow@xxxxxxxxxx).
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _FENV_LIBC_H
+#define _FENV_LIBC_H 1
+
+#include <fenv.h>
+
+/* Definitions from asm/s390-regs-common.h that are needed in glibc. */
+
+
+#define FPC_EXCEPTION_MASK 0xF8000000
+#define FPC_FLAGS_MASK 0x00F80000
+#define FPC_DXC_MASK 0x0000FF00
+#define FPC_RM_MASK 0x00000003
+#define FPC_DFP_RM_MASK 0x00000070
+#define FPC_VALID_MASK ((FPC_EXCEPTION_MASK|FPC_FLAGS_MASK| \
+ FPC_DXC_MASK|FPC_BFP_RM_MASK|FPC_DFP_RM_MASK))
+
+#define FPC_EXCEPTION_MASK_SHIFT 24
+#define FPC_FLAGS_SHIFT 16
+#define FPC_DXC_SHIFT 8
+#define FPC_NOT_FPU_EXCEPTION 0x300
+
+#endif /* _FENV_LIBC_H */
Index: dfp/sysdeps/s390/dfpu/fpu_control.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/dfpu/fpu_control.h 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1,73 @@
+/* FPU control word definitions. Stub version.
+ Copyright (C) 2000, 2008
+ Free Software Foundation, Inc.
+
+ Contributed by Denis Joseph Barrow (djbarrow@xxxxxxxxxx) and
+ Martin Schwidefsky (schwidefsky@xxxxxxxxxx).
+
+ Adjusted for Decimal Floating Point by
+ Andreas Krebbel <Andreas.Krebbel@xxxxxxxxxx>
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _FPU_CONTROL_H
+# define _FPU_CONTROL_H
+
+# include <features.h>
+
+/* bfp rounding control */
+#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */
+#define _FPU_RC_DOWN 0x03
+#define _FPU_RC_UP 0x02
+#define _FPU_RC_ZERO 0x01
+
+/* masking of interrupts */
+#define _FPU_MASK_ZM 0x40 /* zero divide */
+#define _FPU_MASK_OM 0x20 /* overflow */
+#define _FPU_MASK_UM 0x10 /* underflow */
+#define _FPU_MASK_XM 0x08 /* inexact */
+#define _FPU_MASK_IM 0x80 /* invalid operation */
+
+/* dfp rounding control */
+#define _DFPU_RC_NEAREST 0 /* FE_DEC_TONEAREST */
+#define _DFPU_RC_ZERO (1 << 4) /* FE_DEC_TOWARDZERO */
+#define _DFPU_RC_UP (2 << 4) /* FE_DEC_UPWARD */
+#define _DFPU_RC_DOWN (3 << 4) /* FE_DEC_DOWNWARD */
+#define _DFPU_RC_NEARESTFROMZERO (4 << 4) /* FE_DEC_TONEARESTFROMZERO */
+#define _DFPU_RC_NEARESTTOZERO (5 << 4)
+#define _DFPU_RC_AWAYFROMZERO (6 << 4)
+#define _DFPU_RC_PREPFORSHORTPREC (7 << 4)
+
+/* These bits are reserved are not changed. */
+# define _FPU_RESERVED 0x0707001C
+
+/* The fdlibm code requires no interrupts for exceptions. Don't
+ change the rounding mode, it would break long double I/O! */
+#define _FPU_DEFAULT 0x00000000 /* Default value. */
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t;
+
+/* Macros for accessing the hardware control word. */
+#define _FPU_GETCW(cw) __asm__ volatile ("efpc %0,0" : "=d" (cw))
+#define _FPU_SETCW(cw) __asm__ volatile ("sfpc %0,0" : : "d" (cw))
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* _FPU_CONTROL_H */
Index: dfp/sysdeps/s390/dfpu/numdigits.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/dfpu/numdigits.h 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1,155 @@
+/* Number of digits functions, optimized for S/390 z9-ec.
+
+ Copyright (C) 2008 IBM Corporation.
+ Author(s): Andreas Krebbel <Andreas.Krebbel@xxxxxxxxxx>
+
+ The Decimal Floating Point C Library is free software; you can
+ redistribute it and/or modify it under the terms of the GNU Lesser
+ General Public License version 2.1.
+
+ The Decimal Floating Point 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 version 2.1 for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License version 2.1 along with the Decimal Floating Point C Library;
+ if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ Suite 330, Boston, MA 02111-1307 USA.
+
+ Please see dfp/COPYING.txt for more information. */
+
+
+#ifndef _NUMDIGITS_H
+#define _NUMDIGITS_H 1
+
+
+#define NUMDIGITS_SUPPORT 1
+
+#include "dpd-private.h"
+
+#if _DECIMAL_SIZE == 32
+// DECIMAL32 gets widened to DECIMAL64, so it ought to use DECIMAL64 bias
+# define DECIMAL_BIAS (101+297)
+#elif _DECIMAL_SIZE == 64
+# define DECIMAL_BIAS 398
+#elif _DECIMAL_SIZE == 128
+# define DECIMAL_BIAS 6176
+#endif
+
+
+static inline int
+getexp (DEC_TYPE x)
+{
+ int result;
+
+#if _DECIMAL_SIZE == 32
+ _Decimal64 tmp = (_Decimal64)x;
+#elif _DECIMAL_SIZE == 64
+ _Decimal64 tmp = x;
+#elif _DECIMAL_SIZE == 128
+ register _Decimal128 tmp asm ("f0") = x;
+#endif
+
+ asm (
+#if _DECIMAL_SIZE == 128
+ "eextr %0,%1"
+#else /* 32 and 64 bit */
+ "eedtr %0,%1"
+#endif
+ : "=d"(result) : "f"(tmp));
+
+ return result - DECIMAL_BIAS;
+}
+
+
+static inline DEC_TYPE
+setexp (DEC_TYPE x, int exp)
+{
+#if _DECIMAL_SIZE == 32
+ _Decimal64 tmp = (_Decimal64)x;
+#elif _DECIMAL_SIZE == 128
+ register DEC_TYPE tmp asm ("f0") = x;
+#else
+ DEC_TYPE tmp = x;
+#endif
+
+ asm (
+#if _DECIMAL_SIZE == 128
+ "iextr %0,%0,%1"
+#else
+ "iedtr %0,%0,%1"
+#endif
+ : "+f" (tmp) : "r" (exp + DECIMAL_BIAS));
+
+#if _DECIMAL_SIZE == 32
+ return (_Decimal32)tmp;
+#else
+ return tmp;
+#endif
+}
+
+
+static inline int
+numdigits (DEC_TYPE x)
+{
+ int result;
+
+#if _DECIMAL_SIZE == 128
+ register DEC_TYPE tmp asm ("f0") = x;
+#elif _DECIMAL_SIZE == 32
+ _Decimal64 tmp = (_Decimal64)x;
+#else
+ DEC_TYPE tmp = x;
+#endif
+
+ asm (
+#if _DECIMAL_SIZE == 128
+ "esxtr %0,%1"
+#else /* 32 and 64 bit */
+ "esdtr %0,%1"
+#endif
+ : "=d"(result) : "f"(tmp));
+
+ return result;
+}
+
+static DEC_TYPE
+left_justify (DEC_TYPE x)
+{
+#if _DECIMAL_SIZE == 128
+ register DEC_TYPE tmp asm ("f0") = x;
+ register DEC_TYPE rnd asm ("f4");
+#elif _DECIMAL_SIZE == 64
+ DEC_TYPE tmp = x;
+ DEC_TYPE rnd;
+#else
+ _Decimal64 tmp = (_Decimal64)x;
+ _Decimal64 rnd;
+#endif
+
+ int exp;
+
+ asm ("rrdtr %0,%2,%3,1\n\t"
+ "eedtr %1,%0\n\t"
+ /* The following magic numbers result from the precision of the
+ data type minus 1. */
+#if _DECIMAL_SIZE == 32
+ "ahi %1,-6\n\t"
+#elif _DECIMAL_SIZE == 64
+ "ahi %1,-15\n\t"
+#else /* _DECIMAL_SIZE == 128 */
+ "ahi %1,-33\n\t"
+#endif
+ "iedtr %0,%0,%1\n\t"
+ "qadtr %0,%2,%0,1" : "=f"(rnd), "=d"(exp), "+f"(tmp) : "d"(1));
+
+#if _DECIMAL_SIZE == 32
+ return (_Decimal32)rnd;
+#else
+ return rnd;
+#endif
+}
+
+
+#endif /* _NUMDIGITS_H */
Index: dfp/sysdeps/s390/s390-64/z9-ec/fpu/Implies
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/s390-64/z9-ec/fpu/Implies 2008-08-29 15:43:16.000000000 +0200
@@ -0,0 +1 @@
+ieee754r/base-math/
Index: dfp/sysdeps/unix/sysv/linux/s390/Implies
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/unix/sysv/linux/s390/Implies 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1 @@
+dfp/dpd
Index: dfp/sysdeps/s390/fpu/fclrexcpt.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/fpu/fclrexcpt.c 2008-08-29 16:17:36.000000000 +0200
@@ -0,0 +1,43 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 2000, 2008 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This file is a duplicate of the binary floating point version at
+ sysdeps/s390/fpu/fclrexcpt.c . */
+
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ fexcept_t temp;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ _FPU_GETCW (temp);
+ /* Clear the relevant bits. */
+ temp &= ~((excepts << FPC_DXC_SHIFT)|(excepts << FPC_FLAGS_SHIFT));
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+}
Index: dfp/sysdeps/s390/fpu/ftestexcept.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/fpu/ftestexcept.c 2008-08-29 16:17:42.000000000 +0200
@@ -0,0 +1,36 @@
+/* Test exception in current environment.
+ Copyright (C) 2000, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Denis Joseph Barrow (djbarrow@xxxxxxxxxx).
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This file is a duplicate of the binary floating point version at
+ sysdeps/s390/fpu/ftestexcept.c . */
+
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+fetestexcept (int excepts)
+{
+ fexcept_t temp;
+
+ /* Get current exceptions. */
+ _FPU_GETCW (temp);
+ temp = (temp >> FPC_DXC_SHIFT) | (temp >> FPC_FLAGS_SHIFT);
+ return temp & excepts & FE_ALL_EXCEPT;
+}
Index: dfp/sysdeps/s390/fpu/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/fpu/Makefile 2008-08-28 17:32:08.000000000 +0200
@@ -0,0 +1,3 @@
+ifeq ($(subdir),dfp)
+ libdfp-routines += fclrexcpt ftestexcept fraiseexcpt
+endif
Index: dfp/sysdeps/s390/fpu/fraiseexcpt.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dfp/sysdeps/s390/fpu/fraiseexcpt.c 2008-08-29 16:17:14.000000000 +0200
@@ -0,0 +1,75 @@
+/* Raise given exceptions.
+ Copyright (C) 2000, 2002, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Denis Joseph Barrow (djbarrow@xxxxxxxxxx) and
+ Martin Schwidefsky (schwidefsky@xxxxxxxxxx).
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This file is a duplicate of the binary floating point version at
+ sysdeps/s390/fpu/fraiseexcpt.c . */
+
+#include <fenv_libc.h>
+#include <float.h>
+#include <math.h>
+
+
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
+static __inline__ void
+fexceptadd (float d, float e)
+{
+ __asm__ __volatile__ ("aebr %0,%1" : : "f" (d), "f" (e) );
+}
+
+
+int
+feraiseexcept (int excepts)
+{
+ /* Raise exceptions represented by EXPECTS. But we must raise only
+ one signal at a time. It is important that if the overflow/underflow
+ exception and the inexact exception are given at the same time,
+ the overflow/underflow exception follows the inexact exception. */
+
+ /* First: invalid exception. */
+ if (FE_INVALID & excepts)
+ fexceptdiv (0.0, 0.0);
+
+ /* Next: division by zero. */
+ if (FE_DIVBYZERO & excepts)
+ fexceptdiv (1.0, 0.0);
+
+ /* Next: overflow. */
+ if (FE_OVERFLOW & excepts)
+ /* I don't think we can do the same trick as intel so we will have
+ to live with inexact coming also. */
+ fexceptadd (FLT_MAX, 1.0e32);
+
+ /* Next: underflow. */
+ if (FE_UNDERFLOW & excepts)
+ fexceptdiv (FLT_MIN, 3.0);
+
+ /* Last: inexact. */
+ if (FE_INEXACT & excepts)
+ fexceptdiv (2.0, 3.0);
+
+ /* Success. */
+ return 0;
+}