|
From: <sv...@va...> - 2006-01-24 01:01:25
|
Author: sewardj
Date: 2006-01-24 01:01:17 +0000 (Tue, 24 Jan 2006)
New Revision: 5591
Log:
Vex can't simulate floor() or ceil() correctly on ppc32/64 from
glibc-2.3.4 onwards, so just replace the functions with the older
glibc implementation. This is an ugly kludge.
Modified:
trunk/coregrind/vg_preloaded.c
Modified: trunk/coregrind/vg_preloaded.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_preloaded.c 2006-01-24 00:40:35 UTC (rev 5590)
+++ trunk/coregrind/vg_preloaded.c 2006-01-24 01:01:17 UTC (rev 5591)
@@ -65,6 +65,184 @@
*(int *)0 =3D 'x';
}
=20
+/* ---------------------------------------------------------------------
+ Avoid glibc's floor/ceil functions on ppc32/64. In recent glibcs
+ (about 2.3.4 and after) these rely on doing fadd/fsub with with
+ round to +inf/-inf set, which vex does not currently handle
+ correctly. This just reroutes to the glibc default implementations.
+ This is a really ugly hack.
+ ------------------------------------------------------------------ */
+
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
+ */
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+typedef union
+{
+ double value;
+ struct
+ {
+ /*u_int32_t*/ UInt msw;
+ /*u_int32_t*/ UInt lsw;
+ } parts;
+} ieee_double_shape_type;
+
+/* Get two 32 bit ints from a double. */
+#define EXTRACT_WORDS(ix0,ix1,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value =3D (d); \
+ (ix0) =3D ew_u.parts.msw; \
+ (ix1) =3D ew_u.parts.lsw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+#define INSERT_WORDS(d,ix0,ix1) \
+do { \
+ ieee_double_shape_type iw_u; \
+ iw_u.parts.msw =3D (ix0); \
+ iw_u.parts.lsw =3D (ix1); \
+ (d) =3D iw_u.value; \
+} while (0)
+
+static double bit_twiddling_floor ( double x )
+{
+ static const double huge =3D 1.0e300;
+ /*int32_t*/ Int i0,i1,j0;
+ /*u_int32_t*/ UInt i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 =3D ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x !=3D 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=3D0) {i0=3Di1=3D0;}
+ else if(((i0&0x7fffffff)|i1)!=3D0)
+ { i0=3D0xbff00000;i1=3D0;}
+ }
+ } else {
+ i =3D (0x000fffff)>>j0;
+ if(((i0&i)|i1)=3D=3D0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) i0 +=3D (0x00100000)>>j0;
+ i0 &=3D (~i); i1=3D0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0=3D=3D0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i =3D ((/*u_int32_t*/UInt)(0xffffffff))>>(j0-20);
+ if((i1&i)=3D=3D0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) {
+ if(j0=3D=3D20) i0+=3D1;
+ else {
+ j =3D i1+(1<<(52-j0));
+ if(j<i1) i0 +=3D1 ; /* got a carry */
+ i1=3Dj;
+ }
+ }
+ i1 &=3D (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+/* Catch libm.so.6:__floor */
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ZuZufloor)(double);
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ZuZufloor)(double x) {
+ return bit_twiddling_floor(x);
+}
+
+/* Catch libm.so.6:floor */
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,floor)(double);
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,floor)(double x) {
+ return bit_twiddling_floor(x);
+}
+
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+static double bit_twiddling_ceil ( double x )
+{
+ static const double huge =3D 1.0e300;
+ /*int32_t*/ Int i0,i1,j0;
+ /*u_int32_t*/ UInt i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 =3D ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x !=3D 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=3D0x80000000;i1=3D0;}
+ else if((i0|i1)!=3D0) { i0=3D0x3ff00000;i1=3D0;}
+ }
+ } else {
+ i =3D (0x000fffff)>>j0;
+ if(((i0&i)|i1)=3D=3D0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 +=3D (0x00100000)>>j0;
+ i0 &=3D (~i); i1=3D0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0=3D=3D0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i =3D ((/*u_int32_t*/UInt)(0xffffffff))>>(j0-20);
+ if((i1&i)=3D=3D0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(j0=3D=3D20) i0+=3D1;
+ else {
+ j =3D i1 + (1<<(52-j0));
+ if(j<i1) i0+=3D1; /* got a carry */
+ i1 =3D j;
+ }
+ }
+ i1 &=3D (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+/* Catch libm.so.6:__ceil */
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ZuZuceil)(double);
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ZuZuceil)(double x) {
+ return bit_twiddling_ceil(x);
+}
+
+/* Catch libm.so.6:ceil */
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ceil)(double);
+double VG_REPLACE_FUNCTION_ZZ(libmZdsoZd6,ceil)(double x) {
+ return bit_twiddling_ceil(x);
+}
+
+#endif
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
|