hotspot/src/cpu/x86/vm/assembler_x86.cpp
changeset 12955 7cb409520a04
parent 12742 b055b648431a
child 13104 657b387034fb
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Mon Jun 11 22:38:28 2012 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Tue Jun 12 10:02:36 2012 +0200
@@ -6927,21 +6927,42 @@
   addptr(rsp,sizeof(jdouble));
 }
 
+void MacroAssembler::increase_precision() {
+  subptr(rsp, BytesPerWord);
+  fnstcw(Address(rsp, 0));
+  movl(rax, Address(rsp, 0));
+  orl(rax, 0x300);
+  push(rax);
+  fldcw(Address(rsp, 0));
+  pop(rax);
+}
+
+void MacroAssembler::restore_precision() {
+  fldcw(Address(rsp, 0));
+  addptr(rsp, BytesPerWord);
+}
+
 void MacroAssembler::fast_pow() {
   // computes X^Y = 2^(Y * log2(X))
   // if fast computation is not possible, result is NaN. Requires
   // fallback from user of this macro.
+  // increase precision for intermediate steps of the computation
+  increase_precision();
   fyl2x();                 // Stack: (Y*log2(X)) ...
   pow_exp_core_encoding(); // Stack: exp(X) ...
+  restore_precision();
 }
 
 void MacroAssembler::fast_exp() {
   // computes exp(X) = 2^(X * log2(e))
   // if fast computation is not possible, result is NaN. Requires
   // fallback from user of this macro.
+  // increase precision for intermediate steps of the computation
+  increase_precision();
   fldl2e();                // Stack: log2(e) X ...
   fmulp(1);                // Stack: (X*log2(e)) ...
   pow_exp_core_encoding(); // Stack: exp(X) ...
+  restore_precision();
 }
 
 void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) {