1 diff -pruN glibc-2.12-2-gc4ccff1/math/math_private.h glibc-2.12-2-gc4ccff1.new/math/math_private.h
2 --- glibc-2.12-2-gc4ccff1/math/math_private.h 2013-06-07 08:35:52.785442441 -0400
3 +++ glibc-2.12-2-gc4ccff1.new/math/math_private.h 2013-06-07 08:29:35.621042340 -0400
4 @@ -394,4 +394,31 @@ extern void __docos (double __x, double
5 #define libc_feupdateenvf(e) (void) feupdateenv (e)
6 #define libc_feupdateenvl(e) (void) feupdateenv (e)
8 +/* Save and set the rounding mode. The use of fenv_t to store the old mode
9 + allows a target-specific version of this function to avoid converting the
10 + rounding mode from the fpu format. By default we have no choice but to
11 + manipulate the entire env. */
13 +#ifndef libc_feholdsetround
14 +# define libc_feholdsetround(e, r, c) libc_feholdexcept_setround(e, r)
16 +#ifndef libc_feholdsetroundf
17 +# define libc_feholdsetroundf(e, r, c) libc_feholdexcept_setroundf(e, r)
19 +#ifndef libc_feholdsetroundl
20 +# define libc_feholdsetroundl(e, r, c) libc_feholdexcept_setroundl(e, r)
23 +/* ... and the reverse. */
25 +#ifndef libc_feresetround
26 +# define libc_feresetround(e, c) libc_feupdateenv(e)
28 +#ifndef libc_feresetroundf
29 +# define libc_feresetroundf(e, c) libc_feupdateenvf(e)
31 +#ifndef libc_feresetroundl
32 +# define libc_feresetroundl(e, c) libc_feupdateenvl(e)
35 #endif /* _MATH_PRIVATE_H_ */
36 diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/e_exp.c glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/e_exp.c
37 --- glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/e_exp.c 2013-06-07 08:35:52.785442441 -0400
38 +++ glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/e_exp.c 2013-06-07 08:30:21.976222459 -0400
39 @@ -57,7 +57,8 @@ double __ieee754_exp(double x) {
43 - libc_feholdexcept_setround (&env, FE_TONEAREST);
45 + libc_feholdsetround (&env, FE_TONEAREST, changed);
48 m = junk1.i[HIGH_HALF];
49 @@ -152,7 +153,7 @@ double __ieee754_exp(double x) {
50 else { retval = __slowexp(x); goto ret; }
53 - libc_feupdateenv (&env);
54 + libc_feresetround (&env, changed);
58 diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/e_pow.c glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/e_pow.c
59 --- glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/e_pow.c 2013-06-07 08:35:52.785442441 -0400
60 +++ glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/e_pow.c 2013-06-07 08:31:00.294939087 -0400
61 @@ -83,7 +83,8 @@ double __ieee754_pow(double x, double y)
65 - libc_feholdexcept_setround (&env, FE_TONEAREST);
67 + libc_feholdsetround (&env, FE_TONEAREST, changed);
69 z = log1(x,&aa,&error); /* x^y =e^(y log (X)) */
71 @@ -100,7 +101,7 @@ double __ieee754_pow(double x, double y)
72 t = __exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */
73 retval = (t>0)?t:power1(x,y);
75 - libc_feupdateenv (&env);
76 + libc_feresetround (&env, changed);
80 diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/s_sin.c glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/s_sin.c
81 --- glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/s_sin.c 2013-06-07 08:35:52.786442462 -0400
82 +++ glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/s_sin.c 2013-06-07 08:32:08.254822633 -0400
83 @@ -101,7 +101,8 @@ double __sin(double x){
87 - libc_feholdexcept_setround (&env, FE_TONEAREST);
89 + libc_feholdsetround (&env, FE_TONEAREST, changed);
93 @@ -355,7 +356,7 @@ double __sin(double x){
97 - libc_feupdateenv (&env);
98 + libc_feresetround (&env, changed);
102 @@ -374,7 +375,8 @@ double __cos(double x)
106 - libc_feholdexcept_setround (&env, FE_TONEAREST);
108 + libc_feholdsetround (&env, FE_TONEAREST, changed);
112 @@ -623,7 +625,7 @@ double __cos(double x)
116 - libc_feupdateenv (&env);
117 + libc_feresetround (&env, changed);
121 diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/s_tan.c glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/s_tan.c
122 --- glibc-2.12-2-gc4ccff1/sysdeps/ieee754/dbl-64/s_tan.c 2013-06-07 08:35:52.786442462 -0400
123 +++ glibc-2.12-2-gc4ccff1.new/sysdeps/ieee754/dbl-64/s_tan.c 2013-06-07 08:32:39.736162619 -0400
124 @@ -66,7 +66,8 @@ double tan(double x) {
125 int __branred(double, double *, double *);
126 int __mpranred(double, mp_no *, int);
128 - libc_feholdexcept_setround (&env, FE_TONEAREST);
130 + libc_feholdsetround (&env, FE_TONEAREST, changed);
133 num.d = x; ux = num.i[HIGH_HALF];
134 @@ -495,7 +496,7 @@ double tan(double x) {
138 - libc_feupdateenv (&env);
139 + libc_feresetround (&env, changed);
143 diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/fpu/math_private.h glibc-2.12-2-gc4ccff1.new/sysdeps/x86_64/fpu/math_private.h
144 --- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/fpu/math_private.h 2013-06-07 08:35:52.787442488 -0400
145 +++ glibc-2.12-2-gc4ccff1.new/sysdeps/x86_64/fpu/math_private.h 2013-06-07 08:34:35.370109759 -0400
146 @@ -139,3 +139,31 @@ do { \
147 #undef libc_feupdateenvf
148 #define libc_feupdateenvf(e) libc_feupdateenv (e)
149 // #define libc_feupdateenvl(e) (void) feupdateenv (e)
151 +#undef libc_feholdsetround
152 +#define libc_feholdsetround(e, r, c) \
154 + unsigned int mxcsr, new_mxcsr; \
155 + asm ("stmxcsr %0" : "=m" (*&mxcsr)); \
156 + new_mxcsr = (mxcsr & ~0x6000) | ((r) << 3); \
157 + if (__builtin_expect (new_mxcsr != mxcsr, 0)) \
159 + (e)->__mxcsr = mxcsr; \
160 + asm volatile ("ldmxcsr %0" : : "m" (*&new_mxcsr)); \
167 +#undef libc_feresetround
168 +#define libc_feresetround(e, c) \
170 + if (__builtin_expect (c, 0)) \
172 + unsigned int mxcsr; \
173 + asm ("stmxcsr %0" : "=m" (*&mxcsr)); \
174 + mxcsr = (mxcsr & ~0x6000) | ((e)->__mxcsr & 0x6000); \
175 + asm volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); \