Revision: 19885
Author:   [email protected]
Date:     Thu Mar 13 09:45:02 2014 UTC
Log:      A64: Fix Fmov with signalling NaN literals.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/194753002
http://code.google.com/p/v8/source/detail?r=19885

Modified:
 /branches/bleeding_edge/src/a64/assembler-a64.cc
 /branches/bleeding_edge/src/a64/assembler-a64.h
 /branches/bleeding_edge/src/a64/macro-assembler-a64-inl.h
 /branches/bleeding_edge/src/a64/macro-assembler-a64.h
 /branches/bleeding_edge/test/cctest/test-assembler-a64.cc
 /branches/bleeding_edge/test/cctest/test-disasm-a64.cc

=======================================
--- /branches/bleeding_edge/src/a64/assembler-a64.cc Wed Mar 12 15:40:41 2014 UTC +++ /branches/bleeding_edge/src/a64/assembler-a64.cc Thu Mar 13 09:45:02 2014 UTC
@@ -1419,18 +1419,26 @@

 void Assembler::ldr(const Register& rt, uint64_t imm) {
// TODO(all): Constant pool may be garbage collected. Hence we cannot store
-  // TODO(all): arbitrary values in them. Manually move it for now.
-  // TODO(all): Fix MacroAssembler::Fmov when this is implemented.
+  // arbitrary values in them. Manually move it for now. Fix
+  // MacroAssembler::Fmov when this is implemented.
   UNIMPLEMENTED();
 }


 void Assembler::ldr(const FPRegister& ft, double imm) {
// TODO(all): Constant pool may be garbage collected. Hence we cannot store
-  // TODO(all): arbitrary values in them. Manually move it for now.
-  // TODO(all): Fix MacroAssembler::Fmov when this is implemented.
+  // arbitrary values in them. Manually move it for now. Fix
+  // MacroAssembler::Fmov when this is implemented.
   UNIMPLEMENTED();
 }
+
+
+void Assembler::ldr(const FPRegister& ft, float imm) {
+ // TODO(all): Constant pool may be garbage collected. Hence we cannot store
+  // arbitrary values in them. Manually move it for now. Fix
+  // MacroAssembler::Fmov when this is implemented.
+  UNIMPLEMENTED();
+}


 void Assembler::mov(const Register& rd, const Register& rm) {
@@ -1483,16 +1491,16 @@


 void Assembler::fmov(FPRegister fd, double imm) {
-  if (fd.Is64Bits() && IsImmFP64(imm)) {
-    Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
-  } else if (fd.Is32Bits() && IsImmFP32(imm)) {
-    Emit(FMOV_s_imm | Rd(fd) | ImmFP32(static_cast<float>(imm)));
-  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
-    Register zr = AppropriateZeroRegFor(fd);
-    fmov(fd, zr);
-  } else {
-    ldr(fd, imm);
-  }
+  ASSERT(fd.Is64Bits());
+  ASSERT(IsImmFP64(imm));
+  Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
+}
+
+
+void Assembler::fmov(FPRegister fd, float imm) {
+  ASSERT(fd.Is32Bits());
+  ASSERT(IsImmFP32(imm));
+  Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm));
 }


=======================================
--- /branches/bleeding_edge/src/a64/assembler-a64.h Wed Mar 12 15:40:41 2014 UTC +++ /branches/bleeding_edge/src/a64/assembler-a64.h Thu Mar 13 09:45:02 2014 UTC
@@ -1418,6 +1418,7 @@

   // Load literal to FP register.
   void ldr(const FPRegister& ft, double imm);
+  void ldr(const FPRegister& ft, float imm);

   // Move instructions. The default shift of -1 indicates that the move
// instruction will calculate an appropriate 16-bit immediate and left shift
@@ -1496,6 +1497,7 @@
   // FP instructions.
   // Move immediate to FP register.
   void fmov(FPRegister fd, double imm);
+  void fmov(FPRegister fd, float imm);

   // Move FP register to register.
   void fmov(Register rd, FPRegister fn);
=======================================
--- /branches/bleeding_edge/src/a64/macro-assembler-a64-inl.h Wed Mar 12 15:18:40 2014 UTC +++ /branches/bleeding_edge/src/a64/macro-assembler-a64-inl.h Thu Mar 13 09:45:02 2014 UTC
@@ -737,26 +737,44 @@

 void MacroAssembler::Fmov(FPRegister fd, double imm) {
   ASSERT(allow_macro_instructions_);
-  if ((fd.Is64Bits() && IsImmFP64(imm)) ||
-      (fd.Is32Bits() && IsImmFP32(imm)) ||
-      ((imm == 0.0) && (copysign(1.0, imm) == 1.0))) {
-    // These cases can be handled by the Assembler.
+  if (fd.Is32Bits()) {
+    Fmov(fd, static_cast<float>(imm));
+    return;
+  }
+
+  ASSERT(fd.Is64Bits());
+  if (IsImmFP64(imm)) {
     fmov(fd, imm);
+  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
+    fmov(fd, xzr);
   } else {
     UseScratchRegisterScope temps(this);
-    // TODO(all): The Assembler would try to relocate the immediate with
-    // Assembler::ldr(const FPRegister& ft, double imm) but it is not
-    // implemented yet.
-    if (fd.SizeInBits() == kDRegSizeInBits) {
-      Register tmp = temps.AcquireX();
-      Mov(tmp, double_to_rawbits(imm));
-      Fmov(fd, tmp);
-    } else {
-      ASSERT(fd.SizeInBits() == kSRegSizeInBits);
-      Register tmp = temps.AcquireW();
-      Mov(tmp, float_to_rawbits(static_cast<float>(imm)));
-      Fmov(fd, tmp);
-    }
+    Register tmp = temps.AcquireX();
+    // TODO(all): Use Assembler::ldr(const FPRegister& ft, double imm).
+    Mov(tmp, double_to_rawbits(imm));
+    Fmov(fd, tmp);
+  }
+}
+
+
+void MacroAssembler::Fmov(FPRegister fd, float imm) {
+  ASSERT(allow_macro_instructions_);
+  if (fd.Is64Bits()) {
+    Fmov(fd, static_cast<double>(imm));
+    return;
+  }
+
+  ASSERT(fd.Is32Bits());
+  if (IsImmFP32(imm)) {
+    fmov(fd, imm);
+  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
+    fmov(fd, wzr);
+  } else {
+    UseScratchRegisterScope temps(this);
+    Register tmp = temps.AcquireW();
+    // TODO(all): Use Assembler::ldr(const FPRegister& ft, float imm).
+    Mov(tmp, float_to_rawbits(imm));
+    Fmov(fd, tmp);
   }
 }

=======================================
--- /branches/bleeding_edge/src/a64/macro-assembler-a64.h Wed Mar 12 15:18:40 2014 UTC +++ /branches/bleeding_edge/src/a64/macro-assembler-a64.h Thu Mar 13 09:45:02 2014 UTC
@@ -357,7 +357,18 @@
                      const FPRegister& fm);
   inline void Fmov(FPRegister fd, FPRegister fn);
   inline void Fmov(FPRegister fd, Register rn);
+ // Provide explicit double and float interfaces for FP immediate moves, rather
+  // than relying on implicit C++ casts. This allows signalling NaNs to be
+ // preserved when the immediate matches the format of fd. Most systems convert + // signalling NaNs to quiet NaNs when converting between float and double.
   inline void Fmov(FPRegister fd, double imm);
+  inline void Fmov(FPRegister fd, float imm);
+  // Provide a template to allow other types to be converted automatically.
+  template<typename T>
+  void Fmov(FPRegister fd, T imm) {
+    ASSERT(allow_macro_instructions_);
+    Fmov(fd, static_cast<double>(imm));
+  }
   inline void Fmov(Register rd, FPRegister fn);
   inline void Fmsub(const FPRegister& fd,
                     const FPRegister& fn,
@@ -394,7 +405,12 @@
   inline void Ldpsw(const Register& rt,
                     const Register& rt2,
                     const MemOperand& src);
+ // Provide both double and float interfaces for FP immediate loads, rather
+  // than relying on implicit C++ casts. This allows signalling NaNs to be
+ // preserved when the immediate matches the format of fd. Most systems convert + // signalling NaNs to quiet NaNs when converting between float and double.
   inline void Ldr(const FPRegister& ft, double imm);
+  inline void Ldr(const FPRegister& ft, float imm);
   inline void Ldr(const Register& rt, uint64_t imm);
   inline void Lsl(const Register& rd, const Register& rn, unsigned shift);
inline void Lsl(const Register& rd, const Register& rn, const Register& rm);
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-a64.cc Wed Mar 12 15:40:41 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-assembler-a64.cc Thu Mar 13 09:45:02 2014 UTC
@@ -5473,14 +5473,8 @@
   SETUP();

   START();
- // TODO(all): Signalling NaNs are sometimes converted by the C compiler to - // quiet NaNs on implicit casts from float to double. Here, we move the raw - // bits into a W register first, so we get the correct value. Fix Fmov so this
-  // additional step is no longer needed.
-  __ Mov(w0, float_to_rawbits(n));
-  __ Fmov(s0, w0);
-  __ Mov(w0, float_to_rawbits(m));
-  __ Fmov(s1, w0);
+  __ Fmov(s0, n);
+  __ Fmov(s1, m);
   __ Fmin(s28, s0, s1);
   __ Fmax(s29, s0, s1);
   __ Fminnm(s30, s0, s1);
=======================================
--- /branches/bleeding_edge/test/cctest/test-disasm-a64.cc Fri Mar 7 15:20:32 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-disasm-a64.cc Thu Mar 13 09:45:02 2014 UTC
@@ -1273,7 +1273,7 @@
   COMPARE_PREFIX(ldr(x10, 0x1234567890abcdefUL),  "ldr x10, pc+8");
   COMPARE_PREFIX(ldr(w20, 0xfedcba09),  "ldr w20, pc+8");
   COMPARE_PREFIX(ldr(d11, 1.234),  "ldr d11, pc+8");
-  COMPARE_PREFIX(ldr(s22, 2.5),  "ldr s22, pc+8");
+  COMPARE_PREFIX(ldr(s22, 2.5f),  "ldr s22, pc+8");

   CLEANUP();
 }
@@ -1361,8 +1361,8 @@
 TEST_(fmov_imm) {
   SET_UP();

-  COMPARE(fmov(s0, 1.0), "fmov s0, #0x70 (1.0000)");
-  COMPARE(fmov(s31, -13.0), "fmov s31, #0xaa (-13.0000)");
+  COMPARE(fmov(s0, 1.0f), "fmov s0, #0x70 (1.0000)");
+  COMPARE(fmov(s31, -13.0f), "fmov s31, #0xaa (-13.0000)");
   COMPARE(fmov(d1, 1.0), "fmov d1, #0x70 (1.0000)");
   COMPARE(fmov(d29, -13.0), "fmov d29, #0xaa (-13.0000)");

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to