Commit cf07b314 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Fix fp code for mixed-endian ARM.

Review URL: http://codereview.chromium.org/119420

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2140 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2de98f8e
...@@ -4402,14 +4402,21 @@ class ConvertToDoubleStub : public CodeStub { ...@@ -4402,14 +4402,21 @@ class ConvertToDoubleStub : public CodeStub {
void ConvertToDoubleStub::Generate(MacroAssembler* masm) { void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
Label not_special, done; #ifndef BIG_ENDIAN_FLOATING_POINT
Register exponent = result1_;
Register mantissa = result2_;
#else
Register exponent = result2_;
Register mantissa = result1_;
#endif
Label not_special;
// Convert from Smi to integer. // Convert from Smi to integer.
__ mov(source_, Operand(source_, ASR, kSmiTagSize)); __ mov(source_, Operand(source_, ASR, kSmiTagSize));
// Move sign bit from source to destination. This works because the sign bit // Move sign bit from source to destination. This works because the sign bit
// in the exponent word of the double has the same position and polarity as // in the exponent word of the double has the same position and polarity as
// the 2's complement sign bit in a Smi. // the 2's complement sign bit in a Smi.
ASSERT(HeapNumber::kSignMask == 0x80000000u); ASSERT(HeapNumber::kSignMask == 0x80000000u);
__ and_(result1_, source_, Operand(HeapNumber::kSignMask), SetCC); __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC);
// Subtract from 0 if source was negative. // Subtract from 0 if source was negative.
__ rsb(source_, source_, Operand(0), LeaveCC, ne); __ rsb(source_, source_, Operand(0), LeaveCC, ne);
__ cmp(source_, Operand(1)); __ cmp(source_, Operand(1));
...@@ -4420,32 +4427,31 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) { ...@@ -4420,32 +4427,31 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
// For 1 or -1 we need to or in the 0 exponent (biased to 1023). // For 1 or -1 we need to or in the 0 exponent (biased to 1023).
static const uint32_t exponent_word_for_1 = static const uint32_t exponent_word_for_1 =
HeapNumber::kExponentBias << HeapNumber::kExponentShift; HeapNumber::kExponentBias << HeapNumber::kExponentShift;
__ orr(result1_, result1_, Operand(exponent_word_for_1), LeaveCC, ne); __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, ne);
// 1, 0 and -1 all have 0 for the second word. // 1, 0 and -1 all have 0 for the second word.
__ mov(result2_, Operand(0)); __ mov(mantissa, Operand(0));
__ jmp(&done); __ Ret();
__ bind(&not_special); __ bind(&not_special);
// Count leading zeros. Uses result2 for a scratch register on pre-ARM5. // Count leading zeros. Uses result2 for a scratch register on pre-ARM5.
// Gets the wrong answer for 0, but we already checked for that case above. // Gets the wrong answer for 0, but we already checked for that case above.
CountLeadingZeros(masm, source_, result2_, zeros_); CountLeadingZeros(masm, source_, mantissa, zeros_);
// Compute exponent and or it into the exponent register. // Compute exponent and or it into the exponent register.
// We use result2 as a scratch register here. // We use result2 as a scratch register here.
__ rsb(result2_, zeros_, Operand(31 + HeapNumber::kExponentBias)); __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias));
__ orr(result1_, __ orr(exponent,
result1_, exponent,
Operand(result2_, LSL, HeapNumber::kExponentShift)); Operand(mantissa, LSL, HeapNumber::kExponentShift));
// Shift up the source chopping the top bit off. // Shift up the source chopping the top bit off.
__ add(zeros_, zeros_, Operand(1)); __ add(zeros_, zeros_, Operand(1));
// This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0.
__ mov(source_, Operand(source_, LSL, zeros_)); __ mov(source_, Operand(source_, LSL, zeros_));
// Compute lower part of fraction (last 12 bits). // Compute lower part of fraction (last 12 bits).
__ mov(result2_, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord));
// And the top (top 20 bits). // And the top (top 20 bits).
__ orr(result1_, __ orr(exponent,
result1_, exponent,
Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord));
__ bind(&done);
__ Ret(); __ Ret();
} }
...@@ -4626,8 +4632,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -4626,8 +4632,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
__ mov(r5, Operand(r0)); // Overwrite this heap number. __ mov(r5, Operand(r0)); // Overwrite this heap number.
} }
// Calling convention says that second double is in r2 and r3. // Calling convention says that second double is in r2 and r3.
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
__ ldr(r3, FieldMemOperand(r0, HeapNumber::kExponentOffset)); __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4));
__ jmp(&finished_loading_r0); __ jmp(&finished_loading_r0);
__ bind(&r0_is_smi); __ bind(&r0_is_smi);
if (mode == OVERWRITE_RIGHT) { if (mode == OVERWRITE_RIGHT) {
...@@ -4651,8 +4657,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -4651,8 +4657,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
__ mov(r5, Operand(r1)); // Overwrite this heap number. __ mov(r5, Operand(r1)); // Overwrite this heap number.
} }
// Calling convention says that first double is in r0 and r1. // Calling convention says that first double is in r0 and r1.
__ ldr(r0, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
__ ldr(r1, FieldMemOperand(r1, HeapNumber::kExponentOffset)); __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4));
__ jmp(&finished_loading_r1); __ jmp(&finished_loading_r1);
__ bind(&r1_is_smi); __ bind(&r1_is_smi);
if (mode == OVERWRITE_LEFT) { if (mode == OVERWRITE_LEFT) {
...@@ -4688,8 +4694,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -4688,8 +4694,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
__ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset)); __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
#else #else
// Double returned in registers 0 and 1. // Double returned in registers 0 and 1.
__ str(r0, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ str(r1, FieldMemOperand(r4, HeapNumber::kExponentOffset)); __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + 4));
#endif #endif
__ mov(r0, Operand(r4)); __ mov(r0, Operand(r4));
// And we are done. // And we are done.
......
...@@ -1163,10 +1163,17 @@ class HeapNumber: public HeapObject { ...@@ -1163,10 +1163,17 @@ class HeapNumber: public HeapObject {
// Layout description. // Layout description.
static const int kValueOffset = HeapObject::kHeaderSize; static const int kValueOffset = HeapObject::kHeaderSize;
// IEEE doubles are two 32 bit words. The first is just mantissa, the second // IEEE doubles are two 32 bit words. The first is just mantissa, the second
// is a mixture of sign, exponent and mantissa. This is the ordering on a // is a mixture of sign, exponent and mantissa. Our current platforms are all
// little endian machine with little endian double word ordering. // little endian apart from non-EABI arm which is little endian with big
// endian floating point word ordering!
#if !defined(V8_HOST_ARCH_ARM) || __ARM_EABI__
static const int kMantissaOffset = kValueOffset; static const int kMantissaOffset = kValueOffset;
static const int kExponentOffset = kValueOffset + 4; static const int kExponentOffset = kValueOffset + 4;
#else
static const int kMantissaOffset = kValueOffset + 4;
static const int kExponentOffset = kValueOffset;
# define BIG_ENDIAN_FLOATING_POINT 1
#endif
static const int kSize = kValueOffset + kDoubleSize; static const int kSize = kValueOffset + kDoubleSize;
static const uint32_t kSignMask = 0x80000000u; static const uint32_t kSignMask = 0x80000000u;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment