| 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 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);
|
|
|