| Index: src/mips/simulator-mips.cc
|
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
|
| index 5eb79eb7803993240dd75d4c677638d79c54c784..0a2f075cf737b4c0107b56ccc58be2712242dffc 100644
|
| --- a/src/mips/simulator-mips.cc
|
| +++ b/src/mips/simulator-mips.cc
|
| @@ -1091,12 +1091,14 @@ double Simulator::get_fpu_register_double(int fpureg) const {
|
| }
|
|
|
|
|
| -// 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 a0-a3 or f12 and f14.
|
| -void Simulator::GetFpArgs(double* x, double* y) {
|
| +void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
|
| if (!IsMipsSoftFloatABI) {
|
| *x = get_fpu_register_double(12);
|
| *y = get_fpu_register_double(14);
|
| + *z = get_register(a2);
|
| } else {
|
| // We use a char buffer to get around the strict-aliasing rules which
|
| // otherwise allow the compiler to optimize away the copy.
|
| @@ -1107,52 +1109,13 @@ void Simulator::GetFpArgs(double* x, double* y) {
|
| reg_buffer[0] = get_register(a0);
|
| reg_buffer[1] = get_register(a1);
|
| memcpy(x, buffer, sizeof(buffer));
|
| -
|
| // Registers a2 and a3 -> y.
|
| reg_buffer[0] = get_register(a2);
|
| reg_buffer[1] = get_register(a3);
|
| memcpy(y, buffer, sizeof(buffer));
|
| - }
|
| -}
|
| -
|
| -
|
| -// For use in calls that take one double value, constructed either
|
| -// from a0 and a1 or f12.
|
| -void Simulator::GetFpArgs(double* x) {
|
| - if (!IsMipsSoftFloatABI) {
|
| - *x = get_fpu_register_double(12);
|
| - } 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)];
|
| - int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
|
| - // Registers a0 and a1 -> x.
|
| - reg_buffer[0] = get_register(a0);
|
| - reg_buffer[1] = get_register(a1);
|
| - memcpy(x, buffer, sizeof(buffer));
|
| - }
|
| -}
|
| -
|
| -
|
| -// For use in calls that take one double value constructed either
|
| -// from a0 and a1 or f12 and one integer value.
|
| -void Simulator::GetFpArgs(double* x, int32_t* y) {
|
| - if (!IsMipsSoftFloatABI) {
|
| - *x = get_fpu_register_double(12);
|
| - *y = get_register(a2);
|
| - } 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)];
|
| - int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
|
| - // Registers 0 and 1 -> x.
|
| - reg_buffer[0] = get_register(a0);
|
| - reg_buffer[1] = get_register(a1);
|
| - memcpy(x, buffer, sizeof(buffer));
|
| -
|
| - // Register 2 -> y.
|
| + // Register 2 -> z.
|
| reg_buffer[0] = get_register(a2);
|
| - memcpy(y, buffer, sizeof(*y));
|
| + memcpy(z, buffer, sizeof(*z));
|
| }
|
| }
|
|
|
| @@ -1415,10 +1378,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).
|
| @@ -1495,46 +1460,81 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| // simulator. Soft-float has additional abstraction of ExternalReference,
|
| // to support serialization.
|
| if (fp_call) {
|
| - SimulatorRuntimeFPCall target =
|
| - reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| + 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);
|
| + SimulatorRuntimeCall generic_target =
|
| + reinterpret_cast<SimulatorRuntimeCall>(external);
|
| if (::v8::internal::FLAG_trace_sim) {
|
| - 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);
|
| + 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();
|
| break;
|
| }
|
| }
|
| - 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(v0, static_cast<int32_t>(iresult));
|
| + set_register(v1, 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);
|
| - uint64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
| - int32_t gpreg_pair[2];
|
| - memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
|
| - set_register(v0, gpreg_pair[0]);
|
| - set_register(v1, gpreg_pair[1]);
|
| + 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) {
|
| + 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;
|
| + }
|
| }
|
| } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
|
| // See DirectCEntryStub::GenerateCall for explanation of register usage.
|
|
|