From 86e3d4ae56325d387ab87d1110d385526eeb3888 Mon Sep 17 00:00:00 2001 From: "rodolph.perfetta@gmail.com" Date: Wed, 18 Sep 2013 15:13:18 +0000 Subject: [PATCH] ARM: Fix simulator when using hard floating point ABI. BUG=none TEST=make arm.release.check armfloatabi=hard R=ulan@chromium.org Review URL: https://codereview.chromium.org/23496062 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16794 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 2 +- src/arm/simulator-arm.cc | 79 ++++++++++++------------------ src/arm/simulator-arm.h | 9 +++- test/cctest/test-code-stubs-arm.cc | 2 +- 4 files changed, 41 insertions(+), 51 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 732d9f3060..5b80d6facc 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -55,7 +55,7 @@ UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) { #if defined(USE_SIMULATOR) byte* fast_exp_arm_machine_code = NULL; double fast_exp_simulator(double x) { - return Simulator::current(Isolate::Current())->CallFP( + return Simulator::current(Isolate::Current())->CallFPReturnsDouble( fast_exp_arm_machine_code, x, 0); } #endif diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc index def1818630..461d032b99 100644 --- a/src/arm/simulator-arm.cc +++ b/src/arm/simulator-arm.cc @@ -912,6 +912,12 @@ double Simulator::get_double_from_register_pair(int reg) { } +void Simulator::set_register_pair_from_double(int reg, double* value) { + ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); + memcpy(registers_ + reg, value, sizeof(*value)); +} + + void Simulator::set_dw_register(int dreg, const int* dbl) { ASSERT((dreg >= 0) && (dreg < num_d_registers)); registers_[dreg] = dbl[0]; @@ -1026,27 +1032,22 @@ ReturnType Simulator::GetFromVFPRegister(int reg_index) { } -// Runtime FP routines take up to two double arguments and zero -// or one integer arguments. All are consructed here. -// from r0-r3 or d0 and d1. +// Runtime FP routines take: +// - two double arguments +// - one double argument and zero or one integer arguments. +// All are consructed here from r0-r3 or d0, d1 and r0. 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]; + *x = get_double_from_d_register(0); + *y = get_double_from_d_register(1); + *z = get_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[sizeof(*x)]; // Registers 0 and 1 -> x. - OS::MemCopy(buffer, registers_, sizeof(*x)); - OS::MemCopy(x, buffer, sizeof(*x)); + *x = get_double_from_register_pair(0); // Register 2 and 3 -> y. - OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); - OS::MemCopy(y, buffer, sizeof(*y)); + *y = get_double_from_register_pair(2); // Register 2 -> z - memcpy(buffer, registers_ + 2, sizeof(*z)); - memcpy(z, buffer, sizeof(*z)); + *z = get_register(2); } } @@ -1718,32 +1719,6 @@ void Simulator::SoftwareInterrupt(Instruction* instr) { (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); - if (use_eabi_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_registers_[0]; - arg1 = vfp_registers_[1]; - arg2 = vfp_registers_[2]; - arg3 = vfp_registers_[3]; - break; - case ExternalReference::BUILTIN_FP_CALL: - arg0 = vfp_registers_[0]; - arg1 = vfp_registers_[1]; - break; - case ExternalReference::BUILTIN_FP_INT_CALL: - arg0 = vfp_registers_[0]; - arg1 = vfp_registers_[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); @@ -3816,19 +3791,27 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) { } -double Simulator::CallFP(byte* entry, double d0, double d1) { +void Simulator::CallFP(byte* entry, double d0, double d1) { if (use_eabi_hardfloat()) { set_d_register_from_double(0, d0); set_d_register_from_double(1, d1); } else { - int buffer[2]; - ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0)); - OS::MemCopy(buffer, &d0, sizeof(d0)); - set_dw_register(0, buffer); - OS::MemCopy(buffer, &d1, sizeof(d1)); - set_dw_register(2, buffer); + set_register_pair_from_double(0, &d0); + set_register_pair_from_double(2, &d1); } CallInternal(entry); +} + + +int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) { + CallFP(entry, d0, d1); + int32_t result = get_register(r0); + return result; +} + + +double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) { + CallFP(entry, d0, d1); if (use_eabi_hardfloat()) { return get_double_from_d_register(0); } else { diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h index 7fca7432bf..e392c5cb36 100644 --- a/src/arm/simulator-arm.h +++ b/src/arm/simulator-arm.h @@ -163,6 +163,7 @@ class Simulator { void set_register(int reg, int32_t value); int32_t get_register(int reg) const; double get_double_from_register_pair(int reg); + void set_register_pair_from_double(int reg, double* value); void set_dw_register(int dreg, const int* dbl); // Support for VFP. @@ -220,7 +221,9 @@ class Simulator { // which sets up the simulator state and grabs the result on return. int32_t Call(byte* entry, int argument_count, ...); // Alternative: call a 2-argument double function. - double CallFP(byte* entry, double d0, double d1); + void CallFP(byte* entry, double d0, double d1); + int32_t CallFPReturnsInt(byte* entry, double d0, double d1); + double CallFPReturnsDouble(byte* entry, double d0, double d1); // Push an address onto the JS stack. uintptr_t PushAddress(uintptr_t address); @@ -444,6 +447,10 @@ class Simulator { reinterpret_cast(Simulator::current(Isolate::Current())->Call( \ FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) +#define CALL_GENERATED_FP_INT(entry, p0, p1) \ + Simulator::current(Isolate::Current())->CallFPReturnsInt( \ + FUNCTION_ADDR(entry), p0, p1) + #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ Simulator::current(Isolate::Current())->Call( \ entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8) diff --git a/test/cctest/test-code-stubs-arm.cc b/test/cctest/test-code-stubs-arm.cc index c99433edad..54eaa58318 100644 --- a/test/cctest/test-code-stubs-arm.cc +++ b/test/cctest/test-code-stubs-arm.cc @@ -143,7 +143,7 @@ static Isolate* GetIsolateFrom(LocalContext* context) { int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, double from) { #ifdef USE_SIMULATOR - return reinterpret_cast(CALL_GENERATED_CODE(func, from, 0, 0, 0, 0)); + return CALL_GENERATED_FP_INT(func, from, 0); #else return (*func)(from); #endif