X64: Use sahf instruction only on processors that support it.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 1 Sep 2009 11:32:20 +0000 (11:32 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 1 Sep 2009 11:32:20 +0000 (11:32 +0000)
Review URL: http://codereview.chromium.org/183028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2793 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/codegen-x64.cc
src/x64/macro-assembler-x64.cc

index a02557e96a0501a7d551c037c55d275396ef3a1f..6304324da0d6ee5c93e98781eb40728a06301133 100644 (file)
@@ -120,13 +120,23 @@ void CpuFeatures::Probe()  {
   supported_ = kDefaultCpuFeatures | (1 << CPUID);
   { Scope fscope(CPUID);
     __ cpuid();
+    // Move the result from ecx:edx to rdi.
+    __ movl(rdi, rdx);  // Zero-extended to 64 bits.
+    __ shl(rcx, Immediate(32));
+    __ or_(rdi, rcx);
+
+    // Get the sahf supported flag, from CPUID(0x80000001)
+    __ movq(rax, 0x80000001, RelocInfo::NONE);
+    __ cpuid();
   }
   supported_ = kDefaultCpuFeatures;
 
-  // Move the result from ecx:edx to rax and make sure to mark the
-  // CPUID feature as supported.
-  __ movl(rax, rdx);  // Zero-extended to 64 bits.
-  __ shl(rcx, Immediate(32));
+  // Put the CPU flags in rax.
+  // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
+  __ movl(rax, Immediate(1));
+  __ and_(rcx, rax);  // Bit 0 is set if SAHF instruction supported.
+  __ not_(rax);
+  __ and_(rax, rdi);
   __ or_(rax, rcx);
   __ or_(rax, Immediate(1 << CPUID));
 
index 9d602b9ef1ddb493b0fd819e6a0e238055865afa..4d341c6728ebeb625d04eccff56ce916fc995794 100644 (file)
@@ -361,7 +361,12 @@ class CpuFeatures : public AllStatic {
   // Feature flags bit positions. They are mostly based on the CPUID spec.
   // (We assign CPUID itself to one of the currently reserved bits --
   // feel free to change this if needed.)
-  enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
+  enum Feature { SSE3 = 32,
+                 SSE2 = 26,
+                 CMOV = 15,
+                 RDTSC = 4,
+                 CPUID = 10,
+                 SAHF = 0};
   // Detect features of the target CPU. Set safe defaults if the serializer
   // is enabled (snapshots must be portable).
   static void Probe();
index ea6b90a3f24fd1045eae3a20bc73e85d9cb1d90c..7173228fab755357df581b47ebca6c5869e51bfc 100644 (file)
@@ -6546,7 +6546,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
         // One operand is a smi.
 
         // Check whether the non-smi is a heap number.
-        ASSERT_EQ(1, kSmiTagMask);
+        ASSERT_EQ(static_cast<intptr_t>(1), kSmiTagMask);
         // rcx still holds rax & kSmiTag, which is either zero or one.
         __ decq(rcx);  // If rax is a smi, all 1s, else all 0s.
         __ movq(rbx, rdx);
@@ -7722,18 +7722,29 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         __ fild_s(Operand(rsp, 0 * kPointerSize));
         __ fucompp();
         __ fnstsw_ax();
-        __ sahf();  // TODO(X64): Not available.
-        __ j(not_zero, &operand_conversion_failure);
-        __ j(parity_even, &operand_conversion_failure);
-
+        if (CpuFeatures::IsSupported(CpuFeatures::SAHF)) {
+          __ sahf();
+          __ j(not_zero, &operand_conversion_failure);
+          __ j(parity_even, &operand_conversion_failure);
+        } else {
+          __ and_(rax, Immediate(0x4400));
+          __ cmpl(rax, Immediate(0x4000));
+          __ j(not_zero, &operand_conversion_failure);
+        }
         // Check if left operand is int32.
         __ fist_s(Operand(rsp, 1 * kPointerSize));
         __ fild_s(Operand(rsp, 1 * kPointerSize));
         __ fucompp();
         __ fnstsw_ax();
-        __ sahf();  // TODO(X64): Not available. Test bits in ax directly
-        __ j(not_zero, &operand_conversion_failure);
-        __ j(parity_even, &operand_conversion_failure);
+        if (CpuFeatures::IsSupported(CpuFeatures::SAHF)) {
+          __ sahf();
+          __ j(not_zero, &operand_conversion_failure);
+          __ j(parity_even, &operand_conversion_failure);
+        } else {
+          __ and_(rax, Immediate(0x4400));
+          __ cmpl(rax, Immediate(0x4000));
+          __ j(not_zero, &operand_conversion_failure);
+        }
       }
 
       // Get int32 operands and perform bitop.
index 5fd48da75c3a1c6f543782d8e17d12a1ec55c4ee..ae45eaba547c1df29643972f00b783fc7b2be212 100644 (file)
@@ -600,8 +600,14 @@ void MacroAssembler::FCmp() {
   fcompp();
   push(rax);
   fnstsw_ax();
-  // TODO(X64): Check that sahf is safe to use, using CPUProbe.
-  sahf();
+  if (CpuFeatures::IsSupported(CpuFeatures::SAHF)) {
+    sahf();
+  } else {
+    shrl(rax, Immediate(8));
+    and_(rax, Immediate(0xFF));
+    push(rax);
+    popfq();
+  }
   pop(rax);
 }