summaryrefslogtreecommitdiffstats
path: root/lib/msun/i387
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2007-01-06 21:46:23 +0000
committerdas <das@FreeBSD.org>2007-01-06 21:46:23 +0000
commit3d86fb6387a094e2d14a959794b86827ea91d03e (patch)
tree62665f2c7564e85ebe4ba599d4e200d95e83e8fb /lib/msun/i387
parent3e2f039e9decb8137f7c77597bd7a8c4481d3e43 (diff)
downloadFreeBSD-src-3d86fb6387a094e2d14a959794b86827ea91d03e.zip
FreeBSD-src-3d86fb6387a094e2d14a959794b86827ea91d03e.tar.gz
Fix a problem relating to fesetenv() clobbering i387 register stack.
Details: As a side-effect of restoring a saved FP environment, fesetenv() overwrites the tag word, which indicates which i387 registers are in use. Normally this isn't a problem because the calling convention requires the register stack to be empty on function entry and exit. However, fesetenv() is inlined, so we need to tell gcc explicitly that the i387 registers get clobbered. PR: 85101
Diffstat (limited to 'lib/msun/i387')
-rw-r--r--lib/msun/i387/fenv.h13
1 files changed, 12 insertions, 1 deletions
diff --git a/lib/msun/i387/fenv.h b/lib/msun/i387/fenv.h
index cbe9a6b..c4eab02 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);
OpenPOWER on IntegriCloud