DoubleToIStub can't use ip on armv6, because the ubfx impl will clobber it
authorrmcilroy@chromium.org <rmcilroy@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 20 Jan 2014 11:30:48 +0000 (11:30 +0000)
committerrmcilroy@chromium.org <rmcilroy@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 20 Jan 2014 11:30:48 +0000 (11:30 +0000)
This previous change broke DoubleToIStub on armv6:
https://code.google.com/p/v8/source/detail?r=16322

The problem is that DoubleToIStub::Generate assumed that it could safely use the ip register, but on armv6 the ubfx implementation will clobber any previous value stored there.  So instead, pick another register.

Test case:
for (var i=0; i<2; i++) {
v = 4294967295;
v &= -2;
print(v)
}

This should print -2 twice, but on armv6 without this patch, it prints -2 followed by 2046.

This problem causes sunspider's bitops-nsieve-bit, crypto-md5 and crypto-sha1 tests to generate incorrect results (but the results are not checked for validity in sunspider-1.0 as available in chromium, but are checked and reported as incorrect in sunspider-1.0.2).

Thanks to Tomasz Kilarski for helping out with this.

R=bmeurer@chromium.org, rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/131823004

Patch from Mostyn Bramley-Moore <mostynb@opera.com>.

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

src/arm/code-stubs-arm.cc

index ed340ff..cfffa2e 100644 (file)
@@ -665,17 +665,16 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
 
   int double_offset = offset();
   // Account for saved regs if input is sp.
-  if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
+  if (input_reg.is(sp)) double_offset += 3 * kPointerSize;
 
-  // Immediate values for this stub fit in instructions, so it's safe to use ip.
-  Register scratch = ip;
+  Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg);
   Register scratch_low =
       GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
   Register scratch_high =
       GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
   LowDwVfpRegister double_scratch = kScratchDoubleReg;
 
-  __ Push(scratch_high, scratch_low);
+  __ Push(scratch_high, scratch_low, scratch);
 
   if (!skip_fastpath()) {
     // Load double input.
@@ -758,7 +757,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
 
   __ bind(&done);
 
-  __ Pop(scratch_high, scratch_low);
+  __ Pop(scratch_high, scratch_low, scratch);
   __ Ret();
 }