| Index: src/arm/simulator-arm.cc
|
| diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
|
| index 2551e14e4905932a4ad5bd853307bb6c941fac68..e3ef926ca0c0f88afc6c49bed1f55a02a27995a9 100644
|
| --- a/src/arm/simulator-arm.cc
|
| +++ b/src/arm/simulator-arm.cc
|
| @@ -974,12 +974,14 @@ ReturnType Simulator::GetFromVFPRegister(int reg_index) {
|
| }
|
|
|
|
|
| -// For use in calls that take two double values, constructed either
|
| +// Runtime FP routines take up to two double arguments and zero
|
| +// or one integer arguments. All are constructed here,
|
| // from r0-r3 or d0 and d1.
|
| -void Simulator::GetFpArgs(double* x, double* y) {
|
| +void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
|
| if (use_eabi_hardfloat()) {
|
| *x = vfp_registers_[0];
|
| *y = vfp_registers_[1];
|
| + *z = 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.
|
| @@ -990,41 +992,9 @@ void Simulator::GetFpArgs(double* x, double* y) {
|
| // Registers 2 and 3 -> y.
|
| memcpy(buffer, registers_ + 2, sizeof(*y));
|
| memcpy(y, buffer, sizeof(*y));
|
| - }
|
| -}
|
| -
|
| -// For use in calls that take one double value, constructed either
|
| -// from r0 and r1 or d0.
|
| -void Simulator::GetFpArgs(double* x) {
|
| - if (use_eabi_hardfloat()) {
|
| - *x = vfp_registers_[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[sizeof(*x)];
|
| - // Registers 0 and 1 -> x.
|
| - memcpy(buffer, registers_, sizeof(*x));
|
| - memcpy(x, buffer, sizeof(*x));
|
| - }
|
| -}
|
| -
|
| -
|
| -// For use in calls that take one double value constructed either
|
| -// from r0 and r1 or d0 and one integer value.
|
| -void Simulator::GetFpArgs(double* x, int32_t* y) {
|
| - if (use_eabi_hardfloat()) {
|
| - *x = vfp_registers_[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[sizeof(*x)];
|
| - // Registers 0 and 1 -> x.
|
| - memcpy(buffer, registers_, sizeof(*x));
|
| - memcpy(x, buffer, sizeof(*x));
|
| - // Register 2 -> y.
|
| - memcpy(buffer, registers_ + 2, sizeof(*y));
|
| - memcpy(y, buffer, sizeof(*y));
|
| + // Register 2 -> z.
|
| + memcpy(buffer, registers_ + 2, sizeof(*z));
|
| + memcpy(z, buffer, sizeof(*z));
|
| }
|
| }
|
|
|
| @@ -1647,10 +1617,12 @@ typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
|
| int32_t arg3,
|
| int32_t arg4,
|
| int32_t arg5);
|
| -typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
|
| - int32_t arg1,
|
| - int32_t arg2,
|
| - int32_t arg3);
|
| +
|
| +// These prototypes handle the four types of FP calls.
|
| +typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
|
| +typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
|
| +typedef double (*SimulatorRuntimeFPCall)(double darg0);
|
| +typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
|
|
|
| // This signature supports direct call in to API function native callback
|
| // (refer to InvocationCallback in v8.h).
|
| @@ -1716,27 +1688,27 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| intptr_t external =
|
| reinterpret_cast<intptr_t>(redirection->external_function());
|
| if (fp_call) {
|
| + double dval0, dval1; // one or two double parameters
|
| + int32_t ival; // zero or one integer parameters
|
| + int64_t iresult = 0; // integer return value
|
| + double dresult = 0; // double return value
|
| + GetFpArgs(&dval0, &dval1, &ival);
|
| if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
| - SimulatorRuntimeFPCall target =
|
| - reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| - double dval0, dval1;
|
| - int32_t ival;
|
| + SimulatorRuntimeCall generic_target =
|
| + reinterpret_cast<SimulatorRuntimeCall>(external);
|
| 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);
|
| + FUNCTION_ADDR(generic_target), dval0, dval1);
|
| break;
|
| case ExternalReference::BUILTIN_FP_CALL:
|
| - GetFpArgs(&dval0);
|
| PrintF("Call to host function at %p with arg %f",
|
| - FUNCTION_ADDR(target), dval0);
|
| + FUNCTION_ADDR(generic_target), dval0);
|
| 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);
|
| + FUNCTION_ADDR(generic_target), dval0, ival);
|
| break;
|
| default:
|
| UNREACHABLE();
|
| @@ -1748,22 +1720,54 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| PrintF("\n");
|
| }
|
| CHECK(stack_aligned);
|
| - if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
|
| + switch (redirection->type()) {
|
| + case ExternalReference::BUILTIN_COMPARE_CALL: {
|
| + SimulatorRuntimeCompareCall target =
|
| + reinterpret_cast<SimulatorRuntimeCompareCall>(external);
|
| + iresult = target(dval0, dval1);
|
| + set_register(r0, static_cast<int32_t>(iresult));
|
| + set_register(r1, static_cast<int32_t>(iresult >> 32));
|
| + break;
|
| + }
|
| + case ExternalReference::BUILTIN_FP_FP_CALL: {
|
| + SimulatorRuntimeFPFPCall target =
|
| + reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
|
| + dresult = target(dval0, dval1);
|
| + SetFpResult(dresult);
|
| + break;
|
| + }
|
| + case ExternalReference::BUILTIN_FP_CALL: {
|
| SimulatorRuntimeFPCall target =
|
| - reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| - double result = target(arg0, arg1, arg2, arg3);
|
| - SetFpResult(result);
|
| - } else {
|
| - SimulatorRuntimeCall target =
|
| - reinterpret_cast<SimulatorRuntimeCall>(external);
|
| - int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
| - int32_t lo_res = static_cast<int32_t>(result);
|
| - int32_t hi_res = static_cast<int32_t>(result >> 32);
|
| - if (::v8::internal::FLAG_trace_sim) {
|
| - PrintF("Returned %08x\n", lo_res);
|
| + reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| + dresult = target(dval0);
|
| + SetFpResult(dresult);
|
| + break;
|
| + }
|
| + case ExternalReference::BUILTIN_FP_INT_CALL: {
|
| + SimulatorRuntimeFPIntCall target =
|
| + reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
|
| + dresult = target(dval0, ival);
|
| + SetFpResult(dresult);
|
| + break;
|
| + }
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
| + switch (redirection->type()) {
|
| + case ExternalReference::BUILTIN_COMPARE_CALL:
|
| + PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
|
| + break;
|
| + case ExternalReference::BUILTIN_FP_FP_CALL:
|
| + case ExternalReference::BUILTIN_FP_CALL:
|
| + case ExternalReference::BUILTIN_FP_INT_CALL:
|
| + PrintF("Returned %f\n", dresult);
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| }
|
| - set_register(r0, lo_res);
|
| - set_register(r1, hi_res);
|
| }
|
| } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
|
| SimulatorRuntimeDirectApiCall target =
|
|
|