summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Schultz <das@FreeBSD.org>2007-01-06 21:46:23 +0000
committerDavid Schultz <das@FreeBSD.org>2007-01-06 21:46:23 +0000
commit8185b32b5a8bddbb6cf78f87b848bd042324d6d2 (patch)
tree62665f2c7564e85ebe4ba599d4e200d95e83e8fb /lib
parent93e0663877691f5e87e6d0e5968d25a73c951f70 (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/msun/amd64/fenv.h13
-rw-r--r--lib/msun/i387/fenv.h13
2 files changed, 24 insertions, 2 deletions
diff --git a/lib/msun/amd64/fenv.h b/lib/msun/amd64/fenv.h
index cb213c271c5f..b4d7379e8ff0 100644
--- a/lib/msun/amd64/fenv.h
+++ b/lib/msun/amd64/fenv.h
@@ -78,6 +78,9 @@ extern const fenv_t __fe_dfl_env;
#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
+#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
+ : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
+ "st(5)", "st(6)", "st(7)")
#define __fnclex() __asm __volatile("fnclex")
#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
@@ -171,7 +174,15 @@ static __inline int
fesetenv(const fenv_t *__envp)
{
- __fldenv(__envp->__x87);
+ /*
+ * XXX Using fldenvx() instead of fldenv() tells the compiler that this
+ * instruction clobbers the i387 register stack. This happens because
+ * we restore the tag word from the saved environment. Normally, this
+ * would happen anyway and we wouldn't care, because the ABI allows
+ * function calls to clobber the i387 regs. However, fesetenv() is
+ * inlined, so we need to be more careful.
+ */
+ __fldenvx(__envp->__x87);
__ldmxcsr(__envp->__mxcsr);
return (0);
}
diff --git a/lib/msun/i387/fenv.h b/lib/msun/i387/fenv.h
index cbe9a6b6de90..c4eab02d9dfc 100644
--- a/lib/msun/i387/fenv.h
+++ b/lib/msun/i387/fenv.h
@@ -99,6 +99,9 @@ extern const fenv_t __fe_dfl_env;
#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
+#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
+ : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
+ "st(5)", "st(6)", "st(7)")
#define __fnclex() __asm __volatile("fnclex")
#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
@@ -207,7 +210,15 @@ fesetenv(const fenv_t *__envp)
__mxcsr = __get_mxcsr(__env);
__set_mxcsr(__env, 0xffffffff);
- __fldenv(__env);
+ /*
+ * XXX Using fldenvx() instead of fldenv() tells the compiler that this
+ * instruction clobbers the i387 register stack. This happens because
+ * we restore the tag word from the saved environment. Normally, this
+ * would happen anyway and we wouldn't care, because the ABI allows
+ * function calls to clobber the i387 regs. However, fesetenv() is
+ * inlined, so we need to be more careful.
+ */
+ __fldenvx(__env);
if (__HAS_SSE())
__ldmxcsr(__mxcsr);
return (0);