Chromium Code Reviews| Index: src/arm/code-stubs-arm.cc |
| =================================================================== |
| --- src/arm/code-stubs-arm.cc (revision 6560) |
| +++ src/arm/code-stubs-arm.cc (working copy) |
| @@ -2536,24 +2536,100 @@ |
| } |
| -void TypeRecordingBinaryOpStub::GenerateVFPOperation( |
| - MacroAssembler* masm) { |
| - switch (op_) { |
| - case Token::ADD: |
| - __ vadd(d5, d6, d7); |
| - break; |
| - case Token::SUB: |
| - __ vsub(d5, d6, d7); |
| - break; |
| - case Token::MUL: |
| - __ vmul(d5, d6, d7); |
| - break; |
| - case Token::DIV: |
| - __ vdiv(d5, d6, d7); |
| - break; |
| - default: |
| - UNREACHABLE(); |
| +void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, |
| + bool smi_operands, |
| + Label* not_numbers, |
| + Label* gc_required) { |
| + Register left = r1; |
| + Register right = r0; |
| + Register scratch1 = r7; |
| + Register scratch2 = r9; |
| + |
| + // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on |
|
Karl Klose
2011/02/02 10:10:14
Long line.
Søren Thygesen Gjesse
2011/02/02 10:30:30
Done.
|
| + // whether VFP3 is available. |
| + FloatingPointHelper::Destination destination = |
| + CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ? |
| + FloatingPointHelper::kVFPRegisters : |
| + FloatingPointHelper::kCoreRegisters; |
| + |
| + Register heap_number_map = r6; |
| + __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| + |
| + // Allocate new heap number for result. |
| + Register result = r5; |
| + __ AllocateHeapNumber( |
| + result, scratch1, scratch2, heap_number_map, gc_required); |
| + |
| + // Load the operands. |
| + if (smi_operands) { |
| + if (FLAG_debug_code) { |
| + __ AbortIfNotSmi(left); |
| + __ AbortIfNotSmi(right); |
| + } |
| + FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); |
| + } else { |
| + FloatingPointHelper::LoadOperands(masm, |
| + destination, |
| + heap_number_map, |
| + scratch1, |
| + scratch2, |
| + not_numbers); |
| } |
| + |
| + // Calculate the result. |
| + if (destination == FloatingPointHelper::kVFPRegisters) { |
| + // Using VFP registers: |
| + // d6: Left value |
| + // d7: Right value |
| + CpuFeatures::Scope scope(VFP3); |
| + switch (op_) { |
| + case Token::ADD: |
| + __ vadd(d5, d6, d7); |
| + break; |
| + case Token::SUB: |
| + __ vsub(d5, d6, d7); |
| + break; |
| + case Token::MUL: |
| + __ vmul(d5, d6, d7); |
| + break; |
| + case Token::DIV: |
| + __ vdiv(d5, d6, d7); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + |
| + __ sub(r0, result, Operand(kHeapObjectTag)); |
| + __ vstr(d5, r0, HeapNumber::kValueOffset); |
| + __ add(r0, r0, Operand(kHeapObjectTag)); |
| + __ Ret(); |
| + } else { |
| + // Using core registers: |
| + // r0: Left value (least significant part of mantissa). |
| + // r1: Left value (sign, exponent, top of mantissa). |
| + // r2: Right value (least significant part of mantissa). |
| + // r3: Right value (sign, exponent, top of mantissa). |
| + |
| + __ push(lr); // For later. |
| + __ PrepareCallCFunction(4, scratch1); // Two doubles are 4 arguments. |
| + // Call C routine that may not cause GC or other trouble. r5 is callee |
| + // save. |
| + __ CallCFunction(ExternalReference::double_fp_operation(op_), 4); |
| + // Store answer in the overwritable heap number. |
| +#if !defined(USE_ARM_EABI) |
| + // Double returned in fp coprocessor register 0 and 1, encoded as |
| + // register cr8. Offsets must be divisible by 4 for coprocessor so we |
| + // need to substract the tag from r5. |
| + __ sub(scratch1, result, Operand(kHeapObjectTag)); |
| + __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset)); |
| +#else |
| + // Double returned in registers 0 and 1. |
| + __ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset)); |
| +#endif |
| + __ mov(r0, Operand(result)); |
| + // And we are done. |
| + __ pop(pc); |
| + } |
| } |
| @@ -2589,61 +2665,7 @@ |
| // If heap number results are possible generate the result in an allocated |
| // heap number. |
| if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { |
| - FloatingPointHelper::Destination destination = |
| - CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ? |
| - FloatingPointHelper::kVFPRegisters : |
| - FloatingPointHelper::kCoreRegisters; |
| - |
| - Register heap_number_map = r6; |
| - __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| - |
| - // Allocate new heap number for result. |
| - Register result = r5; |
| - __ AllocateHeapNumber( |
| - result, scratch1, scratch2, heap_number_map, gc_required); |
| - |
| - // Load the smis. |
| - FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); |
| - |
| - // Calculate the result. |
| - if (destination == FloatingPointHelper::kVFPRegisters) { |
| - // Using VFP registers: |
| - // d6: Left value |
| - // d7: Right value |
| - CpuFeatures::Scope scope(VFP3); |
| - GenerateVFPOperation(masm); |
| - |
| - __ sub(r0, result, Operand(kHeapObjectTag)); |
| - __ vstr(d5, r0, HeapNumber::kValueOffset); |
| - __ add(r0, r0, Operand(kHeapObjectTag)); |
| - __ Ret(); |
| - } else { |
| - // Using core registers: |
| - // r0: Left value (least significant part of mantissa). |
| - // r1: Left value (sign, exponent, top of mantissa). |
| - // r2: Right value (least significant part of mantissa). |
| - // r3: Right value (sign, exponent, top of mantissa). |
| - |
| - __ push(lr); // For later. |
| - __ PrepareCallCFunction(4, scratch1); // Two doubles are 4 arguments. |
| - // Call C routine that may not cause GC or other trouble. r5 is callee |
| - // save. |
| - __ CallCFunction(ExternalReference::double_fp_operation(op_), 4); |
| - // Store answer in the overwritable heap number. |
| -#if !defined(USE_ARM_EABI) |
| - // Double returned in fp coprocessor register 0 and 1, encoded as |
| - // register cr8. Offsets must be divisible by 4 for coprocessor so we |
| - // need to substract the tag from r5. |
| - __ sub(scratch1, result, Operand(kHeapObjectTag)); |
| - __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset)); |
| -#else |
| - // Double returned in registers 0 and 1. |
| - __ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset)); |
| -#endif |
| - __ mov(r0, Operand(result)); |
| - // And we are done. |
| - __ pop(pc); |
| - } |
| + GenerateFPOperation(masm, true, NULL, gc_required); |
| } |
| __ bind(¬_smis); |
| } |
| @@ -2707,71 +2729,12 @@ |
| op_ == Token::DIV || |
| op_ == Token::MOD); |
| - Register scratch1 = r7; |
| - Register scratch2 = r9; |
| - |
| - Label not_number, call_runtime; |
| + Label not_numbers, call_runtime; |
| ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
| - Register heap_number_map = r6; |
| - __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| + GenerateFPOperation(masm, false, ¬_numbers, &call_runtime); |
| - // Get a heap number object for the result - might be left or right if one |
| - // of these are overwritable. Uses a callee-save register to keep the value |
| - // across the C call which we might use below. |
| - Register result = r5; |
| - GenerateHeapResultAllocation( |
| - masm, result, heap_number_map, scratch1, scratch2, &call_runtime); |
| - |
| - // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on |
| - // whether VFP3 is available. |
| - FloatingPointHelper::Destination destination = |
| - CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ? |
| - FloatingPointHelper::kVFPRegisters : |
| - FloatingPointHelper::kCoreRegisters; |
| - FloatingPointHelper::LoadOperands(masm, |
| - destination, |
| - heap_number_map, |
| - scratch1, |
| - scratch2, |
| - ¬_number); |
| - if (destination == FloatingPointHelper::kVFPRegisters) { |
| - // Use floating point instructions for the binary operation. |
| - CpuFeatures::Scope scope(VFP3); |
| - GenerateVFPOperation(masm); |
| - |
| - // Fill the result into the allocated heap number and return. |
| - __ sub(r0, result, Operand(kHeapObjectTag)); |
| - __ vstr(d5, r0, HeapNumber::kValueOffset); |
| - __ add(r0, r0, Operand(kHeapObjectTag)); |
| - __ Ret(); |
| - |
| - } else { |
| - // Call a C function for the binary operation. |
| - // r0/r1: Left operand |
| - // r2/r3: Right operand |
| - |
| - __ push(lr); // For returning later (no GC after this point). |
| - __ PrepareCallCFunction(4, scratch1); // Two doubles count as 4 arguments. |
| - // Call C routine that may not cause GC or other trouble. result (r5) is |
| - // callee saved. |
| - __ CallCFunction(ExternalReference::double_fp_operation(op_), 4); |
| - // Fill the result into the allocated heap number. |
| - #if !defined(USE_ARM_EABI) |
| - // Double returned in fp coprocessor register 0 and 1, encoded as |
| - // register cr8. Offsets must be divisible by 4 for coprocessor so we |
| - // need to substract the tag from r5. |
| - __ sub(scratch1, result, Operand(kHeapObjectTag)); |
| - __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset)); |
| - #else |
| - // Double returned in registers 0 and 1. |
| - __ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset)); |
| - #endif |
| - __ mov(r0, Operand(result)); |
| - __ pop(pc); // Return to the pushed lr. |
| - } |
| - |
| - __ bind(¬_number); |
| + __ bind(¬_numbers); |
| GenerateTypeTransition(masm); |
| __ bind(&call_runtime); |