patch-2.2.11 linux/arch/alpha/math-emu/sfp-machine.h

Next file: linux/arch/alpha/mm/fault.c
Previous file: linux/arch/alpha/math-emu/ieee-math.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/arch/alpha/math-emu/sfp-machine.h linux/arch/alpha/math-emu/sfp-machine.h
@@ -0,0 +1,625 @@
+/* Machine-dependent software floating-point definitions.  Sparc64 version.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <linux/sched.h>
+#include <asm/fpu.h>
+
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#define _FP_MUL_MEAT_S(R,X,Y)	_FP_MUL_MEAT_1_imm(S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y)	_FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)	_FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		_FP_QNANBIT_S
+#define _FP_NANFRAC_D		_FP_QNANBIT_D
+#define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0
+
+/* On some architectures float-to-int conversions return a result
+ * code.  On others (e.g. Sparc) they return 0
+ */
+#define _FTOI_RESULT		A_r
+
+#define _FP_KEEPNANFRACP 1
+
+/* Alpha Architecture Manual Section 4.7.10.4: Propagating NaN Values,
+ * summary:
+ *
+ * The first of the following rules that is applicable governs the
+ * value returned:
+ *	1: If X is a quiet NaN, copy X to the result.
+ *	2: If X is a signaling NaN, the result is the canonical quiet NaN
+ *	   with the same sign as X
+ *	3: If Y is a quiet NaN, copy Y to the result.
+ *	4: If Y is a signaling NaN, the result is the canonical quiet NaN
+ *	   with the same sign as Y
+ *	5: The result is the canonical quiet NaN with a sign bit of 1
+ *
+ * In addition, in cases (2) and (4) above we set EFLAG_INVALID.
+ */
+
+#define _FP_IS_NAN(fs, Z)	(Z##_c == FP_CLS_NAN)
+#define _FP_IS_QNAN(fs, Z)	(Z##_f & _FP_QNANBIT_##fs)
+
+#define _FP_CHOOSENAN(fs, wc, R, X, Y)				\
+  do {								\
+    R##_r |= (X##_r | Y##_r);					\
+    if(_FP_IS_NAN(fs, Y)) {					\
+	R##_s = Y##_s;						\
+	R##_c = FP_CLS_NAN;					\
+	if(_FP_IS_QNAN(fs, Y)) {	/* Rule 1 */		\
+	    _FP_FRAC_COPY_##wc(R,Y);				\
+	}							\
+	else {				/* Rule 2 */		\
+	    _FP_FRAC_SET_##wc(R,Y##_f | _FP_QNANBIT_##fs); 	\
+	    R##_r = EFLAG_INVALID;				\
+	}							\
+    }								\
+    else if(_FP_IS_NAN(fs, X)) {				\
+	R##_s = X##_s;						\
+	R##_c = FP_CLS_NAN;					\
+	if(_FP_IS_QNAN(fs, X)) {	/* Rule 3 */		\
+	    _FP_FRAC_COPY_##wc(R,X);				\
+	}							\
+	else {				/* Rule 4 */		\
+	    _FP_FRAC_SET_##wc(R,X##_f | _FP_QNANBIT_##fs); 	\
+	    R##_r |= EFLAG_INVALID;				\
+	}							\
+    }								\
+    else {				/* Rule 5 */		\
+	R##_s = 1;						\
+	R##_c = FP_CLS_NAN;					\
+	_FP_FRAC_SET_##wc(R,_FP_QNANBIT_##fs | EFLAG_MASK); 	\
+    }								\
+  } while(0)
+
+/* Rules 3 and 4 don't apply to functions of only one argument */
+#define _FP_CHOOSENAN_1(fs, wc, R, X)				\
+  do {								\
+    if(_FP_IS_NAN(fs, X)) {					\
+	R##_s = X##_s;						\
+	R##_c = FP_CLS_NAN;					\
+	if(_FP_IS_QNAN(fs, X)) {	/* Rule 1 */		\
+	    _FP_FRAC_COPY_##wc(R,X);				\
+	}							\
+	else {				/* Rule 2 */		\
+	    _FP_FRAC_SET_##wc(R,X##_f | _FP_QNANBIT_##fs); 	\
+	    R##_r |= EFLAG_INVALID;				\
+	}							\
+    }								\
+    else {				/* Rule 5 */		\
+	R##_s = 1;						\
+	R##_c = FP_CLS_NAN;					\
+	_FP_FRAC_SET_##wc(R,_FP_QNANBIT_##fs | EFLAG_MASK); 	\
+    }								\
+  } while(0)
+
+#define _FP_CHOOSENAN_SQRT	_FP_CHOOSENAN_1
+
+
+#define __FP_UNPACK_DENORM(fs, wc, X)				\
+    {									\
+	_FP_I_TYPE _shift;						\
+	X##_r |= EFLAG_DENORM;						\
+	if(_FP_DENORM_TO_ZERO) {					\
+	    /* Crunching a nonzero denorm to zero necessarily makes */  \
+	    /* the result inexact */					\
+	    X##_r |= EFLAG_INEXACT;					\
+	    _FP_FRAC_SET_##wc(X, 0);					\
+	    X##_c = FP_CLS_ZERO;					\
+	}								\
+	else {								\
+	    _FP_FRAC_CLZ_##wc(_shift, X);				\
+	    _shift -= _FP_FRACXBITS_##fs;				\
+	    _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));		\
+	    X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;			\
+	    X##_c = FP_CLS_NORMAL;					\
+	}								\
+    }
+
+#define __FP_UNPACK_RAW_1(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+    	(union _FP_UNION_##fs *)val;				\
+								\
+    X##_f = _flo->bits.frac;					\
+    X##_e = _flo->bits.exp;					\
+    X##_s = _flo->bits.sign;					\
+  } while (0)
+
+#define __FP_UNPACK_RAW_2(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    X##_f0 = _flo->bits.frac0;				\
+    X##_f1 = _flo->bits.frac1;				\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+  } while (0)
+
+#define __FP_UNPACK_S(X,val)		\
+  do {					\
+    __FP_UNPACK_RAW_1(S,X,val);		\
+    _FP_UNPACK_CANONICAL(S,1,X);	\
+  } while (0)
+
+#define __FP_UNPACK_D(X,val)		\
+  do {					\
+    __FP_UNPACK_RAW_1(D,X,val);		\
+    _FP_UNPACK_CANONICAL(D,1,X);	\
+  } while (0)
+
+#define __FP_UNPACK_Q(X,val)		\
+  do {					\
+    __FP_UNPACK_RAW_2(Q,X,val);		\
+    _FP_UNPACK_CANONICAL(Q,2,X);	\
+  } while (0)
+
+#define __FP_PACK_RAW_1(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+    	(union _FP_UNION_##fs *)val;				\
+								\
+    _flo->bits.frac = X##_f;					\
+    _flo->bits.exp  = X##_e;					\
+    _flo->bits.sign = X##_s;					\
+  } while (0)
+  
+#define __FP_PACK_RAW_2(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    _flo->bits.frac0 = X##_f0;				\
+    _flo->bits.frac1 = X##_f1;				\
+    _flo->bits.exp   = X##_e;				\
+    _flo->bits.sign  = X##_s;				\
+  } while (0)
+
+
+/* Alpha rules for handling certain exceptional cases are different
+ * enough that we simply define our own versions here to override
+ * the ones in op-common.h
+ */
+
+#define _FP_ADD(fs, wc, R, X, Y)					     \
+do {									     \
+  /* Propagate any flags that may have been set during unpacking */	     \
+  R##_r |= (X##_r | Y##_r);						     \
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))				     \
+  {									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):			     \
+    {									     \
+      /* shift the smaller number so that its exponent matches the larger */ \
+      _FP_I_TYPE diff = X##_e - Y##_e;					     \
+									     \
+      if (diff < 0)							     \
+	{								     \
+	  diff = -diff;							     \
+	  if (diff <= _FP_WFRACBITS_##fs)				     \
+	    _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);		     \
+	  else if (!_FP_FRAC_ZEROP_##wc(X)) {				     \
+	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			     \
+	    R_r |= EFLAG_INEXACT;					     \
+	  }								     \
+	  else								     \
+	    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			     \
+	  R##_e = Y##_e;						     \
+	}								     \
+      else								     \
+	{								     \
+	  if (diff > 0)							     \
+	    {								     \
+	      if (diff <= _FP_WFRACBITS_##fs)				     \
+	        _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);		     \
+	      else if (!_FP_FRAC_ZEROP_##wc(Y))	{			     \
+	        _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			     \
+	         R_r |= EFLAG_INEXACT;					     \
+	      }								     \
+	      else							     \
+	        _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc);		     \
+	    }								     \
+	  R##_e = X##_e;						     \
+	}								     \
+									     \
+      R##_c = FP_CLS_NORMAL;						     \
+									     \
+      if (X##_s == Y##_s)						     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_ADD_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_OVERP_##wc(fs, R))				     \
+	    {								     \
+	      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);		     \
+	      R##_e++;							     \
+	    }								     \
+	}								     \
+      else								     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_SUB_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_ZEROP_##wc(R))					     \
+	    {								     \
+	      /* return an exact zero */				     \
+	      if (FP_ROUNDMODE == FP_RND_MINF)				     \
+		R##_s |= Y##_s;						     \
+	      else							     \
+		R##_s &= Y##_s;						     \
+	      R##_c = FP_CLS_ZERO;					     \
+	    }								     \
+	  else								     \
+	    {								     \
+	      if (_FP_FRAC_NEGP_##wc(R))				     \
+		{							     \
+		  _FP_FRAC_SUB_##wc(R, Y, X);				     \
+		  R##_s = Y##_s;					     \
+		}							     \
+									     \
+	      /* renormalize after subtraction */			     \
+	      _FP_FRAC_CLZ_##wc(diff, R);				     \
+	      diff -= _FP_WFRACXBITS_##fs;				     \
+	      if (diff)							     \
+		{							     \
+		  R##_e -= diff;					     \
+		  _FP_FRAC_SLL_##wc(R, diff);				     \
+		}							     \
+	    }								     \
+	}								     \
+      break;								     \
+    }									     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):				     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):				     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):				     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):				     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):				     \
+    _FP_CHOOSENAN(fs, wc, R, X, Y);					     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):			     \
+    R##_e = X##_e;							     \
+    _FP_FRAC_COPY_##wc(R, X);						     \
+    R##_s = X##_s;							     \
+    R##_c = X##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):			     \
+    R##_e = Y##_e;							     \
+    _FP_FRAC_COPY_##wc(R, Y);						     \
+    R##_s = Y##_s;							     \
+    R##_c = Y##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):				     \
+    if (X##_s != Y##_s)							     \
+      {									     \
+	/* +INF + -INF => NAN */					     \
+	_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);				     \
+	R##_s = X##_s ^ Y##_s;						     \
+	R##_c = FP_CLS_NAN;						     \
+	R##_r |= EFLAG_INVALID;						     \
+	break;								     \
+      }									     \
+    /* FALLTHRU */							     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):				     \
+    R##_s = X##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):			     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):				     \
+    R##_s = Y##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):			     \
+    /* make sure the sign is correct */					     \
+    if (FP_ROUNDMODE == FP_RND_MINF)					     \
+      R##_s = X##_s | Y##_s;						     \
+    else								     \
+      R##_s = X##_s & Y##_s;						     \
+    R##_c = FP_CLS_ZERO;						     \
+    break;								     \
+									     \
+  default:								     \
+    abort();								     \
+  }									     \
+} while (0)
+
+
+#define _FP_MUL(fs, wc, R, X, Y)			\
+do {							\
+  /* Propagate any flags that may have been set during unpacking */	     \
+  R##_r |= (X##_r | Y##_r);						     \
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e + Y##_e + 1;				\
+							\
+    _FP_MUL_MEAT_##fs(R,X,Y);				\
+							\
+    if (_FP_FRAC_OVERP_##wc(fs, R))			\
+      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
+    else						\
+      R##_e--;						\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y);			\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, X);				\
+    R##_c = X##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, Y);				\
+    R##_c = Y##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    R##_s = 1; /* Alpha SRM rule */			\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+#define _FP_DIV(fs, wc, R, X, Y)			\
+do {							\
+  /* Propagate any flags that may have been set during unpacking */	     \
+  R##_r |= (X##_r | Y##_r);						     \
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e - Y##_e;				\
+							\
+    _FP_DIV_MEAT_##fs(R,X,Y);				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y);			\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_ZERO;				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_INF;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    R##_s = 1;	/* Alpha SRM rule */			\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)			\
+  ({									\
+    switch (X##_c)							\
+      {									\
+      case FP_CLS_ZERO:							\
+	r = 0;								\
+	break;								\
+      case FP_CLS_NAN:                                              	\
+	r = 0;								\
+	X##_r |= EFLAG_INVALID;						\
+	break;								\
+      case FP_CLS_INF:							\
+	r = 0;								\
+	X##_r |= (EFLAG_INVALID | EFLAG_INEXACT);			\
+	break;								\
+      case FP_CLS_NORMAL:						\
+	if (X##_e < 0)							\
+	  {								\
+	    r = 0;							\
+	    X##_r |= EFLAG_INEXACT;					\
+	  }								\
+	else								\
+	  {								\
+	    if (X##_e >= rsize - (rsigned != 0)) {			\
+		/* Overflow.  On alpha, set the INV bit and proceed */	\
+		/* JRP - I *believe* the proper behavior is to set */   \
+		/*       INV and write a true zero... need to check */  \
+		X##_r |= EFLAG_INVALID;					\
+		r = 0;							\
+		break;							\
+	    }								\
+	    if (_FP_W_TYPE_SIZE*wc < rsize)				\
+	      {								\
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
+		r <<= X##_e - _FP_WFRACBITS_##fs;			\
+	      }								\
+	    else							\
+	      {								\
+		if (X##_e >= _FP_WFRACBITS_##fs)			\
+		  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
+		else							\
+		  _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
+	      }								\
+	    if (rsigned && X##_s)					\
+	      r = -r;							\
+	  }								\
+	break;								\
+      }									\
+      X##_r;								\
+  })
+
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_TEM ((current->tss.flags)& IEEE_TRAP_ENABLE_MASK)
+
+#define __FPU_TRAP_P(bits) \
+	((__FPU_TEM & (bits)) != 0)
+
+#define __FP_PACK_S(val,X)			\
+({  int __exc = _FP_PACK_CANONICAL(S,1,X);	\
+    if(!__exc || !__FPU_TRAP_P(__exc))		\
+        __FP_PACK_RAW_1(S,val,X);		\
+    __exc;					\
+})
+
+#define __FP_PACK_D(val,X)			\
+({  int __exc = _FP_PACK_CANONICAL(D,1,X);	\
+    if(!__exc || !__FPU_TRAP_P(__exc))		\
+        __FP_PACK_RAW_1(D,val,X);		\
+    __exc;					\
+})
+
+#define __FP_PACK_Q(val,X)			\
+({  int __exc = _FP_PACK_CANONICAL(Q,2,X);	\
+    if(!__exc || !__FPU_TRAP_P(__exc))		\
+        __FP_PACK_RAW_2(Q,val,X);		\
+    __exc;					\
+})
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE	\
+    (((current->tss.flags)&IEEE_CURRENT_RM_MASK)>>IEEE_CURRENT_RM_SHIFT)
+
+#define FP_RND_NEAREST		(FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT)
+#define FP_RND_ZERO		(FPCR_DYN_CHOPPED >> FPCR_DYN_SHIFT)
+#define FP_RND_PINF		(FPCR_DYN_PLUS >> FPCR_DYN_SHIFT)
+#define FP_RND_MINF		(FPCR_DYN_MINUS >> FPCR_DYN_SHIFT)
+
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addq %4,%5,%1; cmpult %1,%4,$28; addq %2,%3,%0; addq %0,$28,%0" \
+	   : "=r" ((UDItype)(sh)), \
+	     "=r" ((UDItype)(sl)) \
+	   : "r" ((UDItype)(ah)), \
+	     "r" ((UDItype)(bh)), \
+	     "r" ((UDItype)(al)), \
+	     "r" ((UDItype)(bl)))
+	   
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subq %4,%5,%1; cmpult %4,%5,$28; subq %2,%3,%0; subq %0,$28,%0"\
+	   : "=r" ((UDItype)(sh)), \
+	     "=&r" ((UDItype)(sl)) \
+	   : "r" ((UDItype)(ah)), \
+	     "r" ((UDItype)(bh)), \
+	     "r" ((UDItype)(al)), \
+	     "r" ((UDItype)(bl)))
+	   
+#define umul_ppmm(wh, wl, u, v) \
+  do { \
+	  __asm__ ("mulq %2,%3,%1; umulh %2,%3,%0" \
+	   : "=r" ((UDItype)(wh)), \
+	     "=&r" ((UDItype)(wl)) \
+	   : "r" ((UDItype)(u)), \
+	     "r" ((UDItype)(v))); \
+  } while (0)
+
+
+#define udiv_qrnnd(q, r, n1, n0, d) 				\
+  do {                                                          \
+    unsigned long __n[2];					\
+    unsigned long __d[2];					\
+    unsigned long __q[2];					\
+    unsigned long __r[2];					\
+    __n[0]=n1; __n[1]=n0; __d[0]=0; __d[1]=d;			\
+    udiv128(__n, __d, __q, __r);				\
+    q=__q[1]; r=__r[1];						\
+  } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1  
+
+#define abort()										\
+	return 0
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN -1
+#endif
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+/* Exception flags. */
+#define EFLAG_INVALID		IEEE_TRAP_ENABLE_INV
+#define EFLAG_OVERFLOW		IEEE_TRAP_ENABLE_OVF
+#define EFLAG_UNDERFLOW		IEEE_TRAP_ENABLE_UNF
+#define EFLAG_DIVZERO		IEEE_TRAP_ENABLE_DZE
+#define EFLAG_INEXACT		IEEE_TRAP_ENABLE_INE
+#define EFLAG_DENORM		IEEE_TRAP_ENABLE_DNO
+#define EFLAG_MASK		IEEE_TRAP_ENABLE_MASK
+
+#ifdef FP_TEST_XXX
+#define _FP_DENORM_TO_ZERO \
+    (tss_flags&IEEE_MAP_DMZ)
+#else
+#define _FP_DENORM_TO_ZERO \
+    ((current->tss.flags)&IEEE_MAP_DMZ)
+#endif
+
+/* Comparison operations */
+#define CMPTXX_EQ		0
+#define CMPTXX_LT		-1
+#define CMPTXX_GT		1
+#define CMPTXX_LE		2
+#define CMPTXX_UN		3

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)