Index: src/arm/macro-assembler-arm.cc |
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc |
index 20dd0b4320dda538a3434df81d857a87686eb053..0fe200bf10fcd4bde07ebbdb705755b58e436b25 100644 |
--- a/src/arm/macro-assembler-arm.cc |
+++ b/src/arm/macro-assembler-arm.cc |
@@ -286,6 +286,15 @@ void MacroAssembler::Move(Register dst, Register src) { |
} |
+void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) { |
+ ASSERT(CpuFeatures::IsSupported(VFP3)); |
+ CpuFeatures::Scope scope(VFP3); |
+ if (!dst.is(src)) { |
+ vmov(dst, src); |
+ } |
+} |
+ |
+ |
void MacroAssembler::And(Register dst, Register src1, const Operand& src2, |
Condition cond) { |
if (!src2.is_reg() && |
@@ -839,7 +848,11 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, |
} |
void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) { |
- vmov(dst, r0, r1); |
+ if (FLAG_hardfloat) { |
+ Move(dst, d0); |
+ } else { |
+ vmov(dst, r0, r1); |
+ } |
} |
@@ -2794,12 +2807,36 @@ void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, |
static const int kRegisterPassedArguments = 4; |
-void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { |
- int frame_alignment = ActivationFrameAlignment(); |
+int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, |
+ int num_double_arguments) { |
+ int stack_passed_words = 0; |
+ if (FLAG_hardfloat) { |
+ // In the hard floating point calling convention, we can use |
+ // all double registers to pass doubles. |
+ if (num_double_arguments > DoubleRegister::kNumRegisters) { |
+ stack_passed_words += |
+ 2 * (num_double_arguments - DoubleRegister::kNumRegisters); |
+ } |
+ } else { |
+ // In the soft floating point calling convention, every double |
+ // argument is passed using two registers. |
+ num_reg_arguments += 2 * num_double_arguments; |
+ } |
// Up to four simple arguments are passed in registers r0..r3. |
- int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ? |
- 0 : num_arguments - kRegisterPassedArguments; |
+ if (num_reg_arguments > kRegisterPassedArguments) { |
+ stack_passed_words += num_reg_arguments - kRegisterPassedArguments; |
+ } |
+ return stack_passed_words; |
+} |
+ |
+ |
+void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
+ int num_double_arguments, |
+ Register scratch) { |
+ int frame_alignment = ActivationFrameAlignment(); |
+ int stack_passed_arguments = CalculateStackPassedWords( |
+ num_reg_arguments, num_double_arguments); |
if (frame_alignment > kPointerSize) { |
// Make stack end at alignment and make room for num_arguments - 4 words |
// and the original value of sp. |
@@ -2814,25 +2851,92 @@ void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { |
} |
+void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
+ Register scratch) { |
+ PrepareCallCFunction(num_reg_arguments, 0, scratch); |
+} |
+ |
+ |
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) { |
+ if (FLAG_hardfloat) { |
+ Move(d0, dreg); |
+ } else { |
+ vmov(r0, r1, dreg); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1, |
+ DoubleRegister dreg2) { |
+ if (FLAG_hardfloat) { |
+ if (dreg2.is(d0)) { |
+ ASSERT(!dreg1.is(d1)); |
+ Move(d1, dreg2); |
+ Move(d0, dreg1); |
+ } else { |
+ Move(d0, dreg1); |
+ Move(d1, dreg2); |
+ } |
+ } else { |
+ vmov(r0, r1, dreg1); |
+ vmov(r2, r3, dreg2); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg, |
+ Register reg) { |
+ if (FLAG_hardfloat) { |
+ Move(d0, dreg); |
+ Move(r0, reg); |
+ } else { |
+ Move(r2, reg); |
+ vmov(r0, r1, dreg); |
+ } |
+} |
+ |
+ |
void MacroAssembler::CallCFunction(ExternalReference function, |
- int num_arguments) { |
- CallCFunctionHelper(no_reg, function, ip, num_arguments); |
+ int num_reg_arguments, |
+ int num_double_arguments) { |
+ CallCFunctionHelper(no_reg, |
+ function, |
+ ip, |
+ num_reg_arguments, |
+ num_double_arguments); |
} |
+ |
void MacroAssembler::CallCFunction(Register function, |
- Register scratch, |
- int num_arguments) { |
+ Register scratch, |
+ int num_reg_arguments, |
+ int num_double_arguments) { |
CallCFunctionHelper(function, |
ExternalReference::the_hole_value_location(isolate()), |
scratch, |
- num_arguments); |
+ num_reg_arguments, |
+ num_double_arguments); |
+} |
+ |
+ |
+void MacroAssembler::CallCFunction(ExternalReference function, |
+ int num_arguments) { |
+ CallCFunction(function, num_arguments, 0); |
+} |
+ |
+ |
+void MacroAssembler::CallCFunction(Register function, |
+ Register scratch, |
+ int num_arguments) { |
+ CallCFunction(function, scratch, num_arguments, 0); |
} |
void MacroAssembler::CallCFunctionHelper(Register function, |
ExternalReference function_reference, |
Register scratch, |
- int num_arguments) { |
+ int num_reg_arguments, |
+ int num_double_arguments) { |
// Make sure that the stack is aligned before calling a C function unless |
// running in the simulator. The simulator has its own alignment check which |
// provides more information. |
@@ -2861,8 +2965,8 @@ void MacroAssembler::CallCFunctionHelper(Register function, |
function = scratch; |
} |
Call(function); |
- int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ? |
- 0 : num_arguments - kRegisterPassedArguments; |
+ int stack_passed_arguments = CalculateStackPassedWords( |
+ num_reg_arguments, num_double_arguments); |
if (ActivationFrameAlignment() > kPointerSize) { |
ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
} else { |