Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index 1f55f73a0203fd3c33c5e7ca069e16378523241c..801b63f44e7608b9f092bd14d4acc715a215deda 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -1009,26 +1009,74 @@ double Simulator::get_double_from_d_register(int dreg) { |
} |
-// For use in calls that take two double values, constructed from r0, r1, r2 |
-// and r3. |
+// For use in calls that take two double values, constructed either |
+// from r0-r3 or d0 and d1. |
void Simulator::GetFpArgs(double* x, double* y) { |
- // We use a char buffer to get around the strict-aliasing rules which |
- // otherwise allow the compiler to optimize away the copy. |
- char buffer[2 * sizeof(registers_[0])]; |
- // Registers 0 and 1 -> x. |
- memcpy(buffer, registers_, sizeof(buffer)); |
- memcpy(x, buffer, sizeof(buffer)); |
- // Registers 2 and 3 -> y. |
- memcpy(buffer, registers_ + 2, sizeof(buffer)); |
- memcpy(y, buffer, sizeof(buffer)); |
+ if (FLAG_hardfloat) { |
+ *x = vfp_register[0]; |
+ *y = vfp_register[1]; |
+ } else { |
+ // We use a char buffer to get around the strict-aliasing rules which |
+ // otherwise allow the compiler to optimize away the copy. |
+ char buffer[2 * sizeof(registers_[0])]; |
+ // Registers 0 and 1 -> x. |
+ memcpy(buffer, registers_, sizeof(buffer)); |
+ memcpy(x, buffer, sizeof(buffer)); |
+ // Registers 2 and 3 -> y. |
+ memcpy(buffer, registers_ + 2, sizeof(buffer)); |
+ memcpy(y, buffer, sizeof(buffer)); |
+ } |
+} |
+ |
+// For use in calls that take one double value, constructed either |
+// from r0 and r1 or d0. |
+void Simulator::GetFpArgs(double* x) { |
+ if (FLAG_hardfloat) { |
+ *x = vfp_register[0]; |
+ } else { |
+ // We use a char buffer to get around the strict-aliasing rules which |
+ // otherwise allow the compiler to optimize away the copy. |
+ char buffer[2 * sizeof(registers_[0])]; |
+ // Registers 0 and 1 -> x. |
+ memcpy(buffer, registers_, sizeof(buffer)); |
+ memcpy(x, buffer, sizeof(buffer)); |
+ } |
+} |
+ |
+ |
+// For use in calls that take two double values, constructed either |
+// from r0-r3 or d0 and d1. |
+void Simulator::GetFpArgs(double* x, int32_t* y) { |
+ if (FLAG_hardfloat) { |
+ *x = vfp_register[0]; |
+ *y = registers_[1]; |
+ } else { |
+ // We use a char buffer to get around the strict-aliasing rules which |
+ // otherwise allow the compiler to optimize away the copy. |
+ char buffer[2 * sizeof(registers_[0])]; |
+ // Registers 0 and 1 -> x. |
+ memcpy(buffer, registers_, sizeof(buffer)); |
+ memcpy(x, buffer, sizeof(buffer)); |
+ // Registers 2 and 3 -> y. |
+ memcpy(buffer, registers_ + 2, sizeof(buffer)); |
+ memcpy(y, buffer, sizeof(buffer)); |
+ } |
} |
+// The return value is either in r0/r1 or d0. |
void Simulator::SetFpResult(const double& result) { |
- char buffer[2 * sizeof(registers_[0])]; |
- memcpy(buffer, &result, sizeof(buffer)); |
- // result -> registers 0 and 1. |
- memcpy(registers_, buffer, sizeof(buffer)); |
+ if (FLAG_hardfloat) { |
+ char buffer[2 * sizeof(vfp_register[0])]; |
+ memcpy(buffer, &result, sizeof(buffer)); |
+ // Copy result to d0. |
+ memcpy(vfp_register, buffer, sizeof(buffer)); |
+ } else { |
+ char buffer[2 * sizeof(registers_[0])]; |
+ memcpy(buffer, &result, sizeof(buffer)); |
+ // Copy result to r0 and r1. |
+ memcpy(registers_, buffer, sizeof(buffer)); |
+ } |
} |
@@ -1685,19 +1733,69 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { |
int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
int32_t arg4 = stack_pointer[0]; |
int32_t arg5 = stack_pointer[1]; |
+ bool fp_call = |
+ (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || |
+ (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || |
+ (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || |
+ (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); |
+ if (FLAG_hardfloat) { |
+ // With the hard floating point calling convention, double |
+ // arguments are passed in VFP registers. Fetch the arguments |
+ // from there and call the builtin using soft floating point |
+ // convention. |
+ switch (redirection->type()) { |
+ case ExternalReference::BUILTIN_FP_FP_CALL: |
+ case ExternalReference::BUILTIN_COMPARE_CALL: |
+ arg0 = vfp_register[0]; |
+ arg1 = vfp_register[1]; |
+ arg2 = vfp_register[2]; |
+ arg3 = vfp_register[3]; |
+ break; |
+ case ExternalReference::BUILTIN_FP_CALL: |
+ arg0 = vfp_register[0]; |
+ arg1 = vfp_register[1]; |
+ break; |
+ case ExternalReference::BUILTIN_FP_INT_CALL: |
+ arg0 = vfp_register[0]; |
+ arg1 = vfp_register[1]; |
+ arg2 = get_register(0); |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
// This is dodgy but it works because the C entry stubs are never moved. |
// See comment in codegen-arm.cc and bug 1242173. |
int32_t saved_lr = get_register(lr); |
intptr_t external = |
reinterpret_cast<intptr_t>(redirection->external_function()); |
- if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
+ if (fp_call) { |
SimulatorRuntimeFPCall target = |
reinterpret_cast<SimulatorRuntimeFPCall>(external); |
if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
- double x, y; |
- GetFpArgs(&x, &y); |
- PrintF("Call to host function at %p with args %f, %f", |
- FUNCTION_ADDR(target), x, y); |
+ double dval0, dval1; |
+ int32_t ival; |
+ switch (redirection->type()) { |
+ case ExternalReference::BUILTIN_FP_FP_CALL: |
+ case ExternalReference::BUILTIN_COMPARE_CALL: |
+ GetFpArgs(&dval0, &dval1); |
+ PrintF("Call to host function at %p with args %f, %f", |
+ FUNCTION_ADDR(target), dval0, dval1); |
+ break; |
+ case ExternalReference::BUILTIN_FP_CALL: |
+ GetFpArgs(&dval0); |
+ PrintF("Call to host function at %p with arg %f", |
+ FUNCTION_ADDR(target), dval1); |
+ break; |
+ case ExternalReference::BUILTIN_FP_INT_CALL: |
+ GetFpArgs(&dval0, &ival); |
+ PrintF("Call to host function at %p with args %f, %d", |
+ FUNCTION_ADDR(target), dval0, ival); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
if (!stack_aligned) { |
PrintF(" with unaligned stack %08x\n", get_register(sp)); |
} |
@@ -1705,7 +1803,9 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { |
} |
CHECK(stack_aligned); |
double result = target(arg0, arg1, arg2, arg3); |
- SetFpResult(result); |
+ if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { |
+ SetFpResult(result); |
+ } |
} else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { |
SimulatorRuntimeDirectApiCall target = |
reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); |