From 7ba01a83e9abaabcd0fad9c19e2e3145cf6adf6a Mon Sep 17 00:00:00 2001 From: "karlklose@chromium.org" Date: Wed, 27 Apr 2011 14:29:25 +0000 Subject: [PATCH] Implement hardfloat calling convention in macro assembler and simulator. Review URL: http://codereview.chromium.org/6874007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7693 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 71 ++++++++++++----- src/arm/lithium-codegen-arm.cc | 30 ++++--- src/arm/macro-assembler-arm.cc | 130 +++++++++++++++++++++++++++--- src/arm/macro-assembler-arm.h | 37 +++++++-- src/arm/simulator-arm.cc | 142 ++++++++++++++++++++++++++++----- src/arm/simulator-arm.h | 5 +- src/assembler.cc | 15 ++-- src/assembler.h | 14 +++- src/flag-definitions.h | 2 + tools/test.py | 7 ++ 10 files changed, 365 insertions(+), 88 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 4cc5ef347..721af0e18 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -830,14 +830,26 @@ void FloatingPointHelper::CallCCodeForDoubleOperation( // Push the current return address before the C call. Return will be // through pop(pc) below. __ push(lr); - __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments. + __ PrepareCallCFunction(0, 2, scratch); + if (FLAG_hardfloat) { + ASSERT(CpuFeatures::IsSupported(VFP3)); + CpuFeatures::Scope scope(VFP3); + __ vmov(d0, r0, r1); + __ vmov(d1, r2, r3); + } // Call C routine that may not cause GC or other trouble. __ CallCFunction(ExternalReference::double_fp_operation(op, masm->isolate()), - 4); + 0, 2); // Store answer in the overwritable heap number. Double returned in - // registers r0 and r1. - __ Strd(r0, r1, FieldMemOperand(heap_number_result, - HeapNumber::kValueOffset)); + // registers r0 and r1 or in d0. + if (FLAG_hardfloat) { + CpuFeatures::Scope scope(VFP3); + __ vstr(d0, + FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); + } else { + __ Strd(r0, r1, FieldMemOperand(heap_number_result, + HeapNumber::kValueOffset)); + } // Place heap_number_result in r0 and return to the pushed return address. __ mov(r0, Operand(heap_number_result)); __ pop(pc); @@ -1179,8 +1191,15 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, // Call a native function to do a comparison between two non-NaNs. // Call C routine that may not cause GC or other trouble. __ push(lr); - __ PrepareCallCFunction(4, r5); // Two doubles count as 4 arguments. - __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), 4); + __ PrepareCallCFunction(0, 2, r5); + if (FLAG_hardfloat) { + ASSERT(CpuFeatures::IsSupported(VFP3)); + CpuFeatures::Scope scope(VFP3); + __ vmov(d0, r0, r1); + __ vmov(d1, r2, r3); + } + __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), + 0, 2); __ pop(pc); // Return. } } @@ -2834,17 +2853,24 @@ void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, Isolate* isolate = masm->isolate(); __ push(lr); - __ PrepareCallCFunction(2, scratch); - __ vmov(r0, r1, d2); + __ PrepareCallCFunction(0, 1, scratch); + if (FLAG_hardfloat) { + __ vmov(d0, d2); + } else { + __ vmov(r0, r1, d2); + } switch (type_) { case TranscendentalCache::SIN: - __ CallCFunction(ExternalReference::math_sin_double_function(isolate), 2); + __ CallCFunction(ExternalReference::math_sin_double_function(isolate), + 0, 1); break; case TranscendentalCache::COS: - __ CallCFunction(ExternalReference::math_cos_double_function(isolate), 2); + __ CallCFunction(ExternalReference::math_cos_double_function(isolate), + 0, 1); break; case TranscendentalCache::LOG: - __ CallCFunction(ExternalReference::math_log_double_function(isolate), 2); + __ CallCFunction(ExternalReference::math_log_double_function(isolate), + 0, 1); break; default: UNIMPLEMENTED(); @@ -3061,11 +3087,11 @@ void MathPowStub::Generate(MacroAssembler* masm) { heapnumbermap, &call_runtime); __ push(lr); - __ PrepareCallCFunction(3, scratch); - __ mov(r2, exponent); - __ vmov(r0, r1, double_base); + __ PrepareCallCFunction(1, 1, scratch); + __ SetCallCDoubleArguments(double_base, exponent); __ CallCFunction( - ExternalReference::power_double_int_function(masm->isolate()), 3); + ExternalReference::power_double_int_function(masm->isolate()), + 1, 1); __ pop(lr); __ GetCFunctionDoubleResult(double_result); __ vstr(double_result, @@ -3091,11 +3117,11 @@ void MathPowStub::Generate(MacroAssembler* masm) { heapnumbermap, &call_runtime); __ push(lr); - __ PrepareCallCFunction(4, scratch); - __ vmov(r0, r1, double_base); - __ vmov(r2, r3, double_exponent); + __ PrepareCallCFunction(0, 2, scratch); + __ SetCallCDoubleArguments(double_base, double_exponent); __ CallCFunction( - ExternalReference::power_double_double_function(masm->isolate()), 4); + ExternalReference::power_double_double_function(masm->isolate()), + 0, 2); __ pop(lr); __ GetCFunctionDoubleResult(double_result); __ vstr(double_result, @@ -3139,8 +3165,9 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, if (do_gc) { // Passing r0. - __ PrepareCallCFunction(1, r1); - __ CallCFunction(ExternalReference::perform_gc_function(isolate), 1); + __ PrepareCallCFunction(1, 0, r1); + __ CallCFunction(ExternalReference::perform_gc_function(isolate), + 1, 0); } ExternalReference scope_depth = diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 135727c5b..129a0b60d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1345,11 +1345,11 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) { // Save r0-r3 on the stack. __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); - __ PrepareCallCFunction(4, scratch0()); - __ vmov(r0, r1, left); - __ vmov(r2, r3, right); + __ PrepareCallCFunction(0, 2, scratch0()); + __ SetCallCDoubleArguments(left, right); __ CallCFunction( - ExternalReference::double_fp_operation(Token::MOD, isolate()), 4); + ExternalReference::double_fp_operation(Token::MOD, isolate()), + 0, 2); // Move the result in the double result register. __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); @@ -2966,19 +2966,18 @@ void LCodeGen::DoPower(LPower* instr) { Representation exponent_type = instr->hydrogen()->right()->representation(); if (exponent_type.IsDouble()) { // Prepare arguments and call C function. - __ PrepareCallCFunction(4, scratch); - __ vmov(r0, r1, ToDoubleRegister(left)); - __ vmov(r2, r3, ToDoubleRegister(right)); + __ PrepareCallCFunction(0, 2, scratch); + __ SetCallCDoubleArguments(ToDoubleRegister(left), + ToDoubleRegister(right)); __ CallCFunction( - ExternalReference::power_double_double_function(isolate()), 4); + ExternalReference::power_double_double_function(isolate()), 0, 2); } else if (exponent_type.IsInteger32()) { ASSERT(ToRegister(right).is(r0)); // Prepare arguments and call C function. - __ PrepareCallCFunction(4, scratch); - __ mov(r2, ToRegister(right)); - __ vmov(r0, r1, ToDoubleRegister(left)); + __ PrepareCallCFunction(1, 1, scratch); + __ SetCallCDoubleArguments(ToDoubleRegister(left), ToRegister(right)); __ CallCFunction( - ExternalReference::power_double_int_function(isolate()), 4); + ExternalReference::power_double_int_function(isolate()), 1, 1); } else { ASSERT(exponent_type.IsTagged()); ASSERT(instr->hydrogen()->left()->representation().IsDouble()); @@ -3008,11 +3007,10 @@ void LCodeGen::DoPower(LPower* instr) { // Prepare arguments and call C function. __ bind(&call); - __ PrepareCallCFunction(4, scratch); - __ vmov(r0, r1, ToDoubleRegister(left)); - __ vmov(r2, r3, result_reg); + __ PrepareCallCFunction(0, 2, scratch); + __ SetCallCDoubleArguments(ToDoubleRegister(left), result_reg); __ CallCFunction( - ExternalReference::power_double_double_function(isolate()), 4); + ExternalReference::power_double_double_function(isolate()), 0, 2); } // Store the result in the result register. __ GetCFunctionDoubleResult(result_reg); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 20dd0b432..0fe200bf1 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 { diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index ab5efb0b3..e3a78f934 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -142,9 +142,12 @@ class MacroAssembler: public Assembler { Condition cond = al); void Call(Label* target); + + // Register move. May do nothing if the registers are identical. void Move(Register dst, Handle value); - // May do nothing if the registers are identical. void Move(Register dst, Register src); + void Move(DoubleRegister dst, DoubleRegister src); + // Jumps to the label at the index given by the Smi in "index". void SmiJumpTable(Register index, Vector targets); // Load an object from the root table. @@ -740,15 +743,32 @@ class MacroAssembler: public Assembler { int num_arguments, int result_size); + int CalculateStackPassedWords(int num_reg_arguments, + int num_double_arguments); + // Before calling a C-function from generated code, align arguments on stack. // After aligning the frame, non-register arguments must be stored in // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments - // are word sized. + // are word sized. If double arguments are used, this function assumes that + // all double arguments are stored before core registers; otherwise the + // correct alignment of the double values is not guaranteed. // Some compilers/platforms require the stack to be aligned when calling // C++ code. // Needs a scratch register to do some arithmetic. This register will be // trashed. - void PrepareCallCFunction(int num_arguments, Register scratch); + void PrepareCallCFunction(int num_reg_arguments, + int num_double_registers, + Register scratch); + void PrepareCallCFunction(int num_reg_arguments, + Register scratch); + + // There are two ways of passing double arguments on ARM, depending on + // whether soft or hard floating point ABI is used. These functions + // abstract parameter passing for the three different ways we call + // C functions from generated code. + void SetCallCDoubleArguments(DoubleRegister dreg); + void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2); + void SetCallCDoubleArguments(DoubleRegister dreg, Register reg); // Calls a C function and cleans up the space for arguments allocated // by PrepareCallCFunction. The called function is not allowed to trigger a @@ -757,6 +777,12 @@ class MacroAssembler: public Assembler { // function). void CallCFunction(ExternalReference function, int num_arguments); void CallCFunction(Register function, Register scratch, int num_arguments); + void CallCFunction(ExternalReference function, + int num_reg_arguments, + int num_double_arguments); + void CallCFunction(Register function, Register scratch, + int num_reg_arguments, + int num_double_arguments); void GetCFunctionDoubleResult(const DoubleRegister dst); @@ -954,7 +980,8 @@ class MacroAssembler: public Assembler { void CallCFunctionHelper(Register function, ExternalReference function_reference, Register scratch, - int num_arguments); + int num_reg_arguments, + int num_double_arguments); void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); int CallSize(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc index 1f55f73a0..801b63f44 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(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(redirection->external_function()); - if (redirection->type() == ExternalReference::FP_RETURN_CALL) { + if (fp_call) { SimulatorRuntimeFPCall target = reinterpret_cast(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(external); diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h index 525063835..fa5466d35 100644 --- a/src/arm/simulator-arm.h +++ b/src/arm/simulator-arm.h @@ -310,9 +310,10 @@ class Simulator { void* external_function, v8::internal::ExternalReference::Type type); - // For use in calls that take two double values, constructed from r0, r1, r2 - // and r3. + // For use in calls that take double value arguments. void GetFpArgs(double* x, double* y); + void GetFpArgs(double* x); + void GetFpArgs(double* x, int32_t* y); void SetFpResult(const double& result); void TrashCallerSaveRegisters(); diff --git a/src/assembler.cc b/src/assembler.cc index ca30e19cb..18a14c002 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -887,7 +887,7 @@ ExternalReference ExternalReference::math_sin_double_function( Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(math_sin_double), - FP_RETURN_CALL)); + BUILTIN_FP_CALL)); } @@ -895,7 +895,7 @@ ExternalReference ExternalReference::math_cos_double_function( Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(math_cos_double), - FP_RETURN_CALL)); + BUILTIN_FP_CALL)); } @@ -903,7 +903,7 @@ ExternalReference ExternalReference::math_log_double_function( Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(math_log_double), - FP_RETURN_CALL)); + BUILTIN_FP_CALL)); } @@ -946,7 +946,7 @@ ExternalReference ExternalReference::power_double_double_function( Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(power_double_double), - FP_RETURN_CALL)); + BUILTIN_FP_FP_CALL)); } @@ -954,7 +954,7 @@ ExternalReference ExternalReference::power_double_int_function( Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(power_double_int), - FP_RETURN_CALL)); + BUILTIN_FP_INT_CALL)); } @@ -987,17 +987,16 @@ ExternalReference ExternalReference::double_fp_operation( default: UNREACHABLE(); } - // Passing true as 2nd parameter indicates that they return an fp value. return ExternalReference(Redirect(isolate, FUNCTION_ADDR(function), - FP_RETURN_CALL)); + BUILTIN_FP_FP_CALL)); } ExternalReference ExternalReference::compare_doubles(Isolate* isolate) { return ExternalReference(Redirect(isolate, FUNCTION_ADDR(native_compare_doubles), - BUILTIN_CALL)); + BUILTIN_COMPARE_CALL)); } diff --git a/src/assembler.h b/src/assembler.h index e8cecc3fd..2e6ee26e3 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -501,9 +501,21 @@ class ExternalReference BASE_EMBEDDED { // MaybeObject* f(v8::internal::Arguments). BUILTIN_CALL, // default + // Builtin that takes float arguments and returns an int. + // int f(double, double). + BUILTIN_COMPARE_CALL, + // Builtin call that returns floating point. // double f(double, double). - FP_RETURN_CALL, + BUILTIN_FP_FP_CALL, + + // Builtin call that returns floating point. + // double f(double). + BUILTIN_FP_CALL, + + // Builtin call that returns floating point. + // double f(double, int). + BUILTIN_FP_INT_CALL, // Direct call to API function callback. // Handle f(v8::Arguments&) diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 3b5c087ed..5c165e220 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -144,6 +144,8 @@ DEFINE_int(stress_runs, 0, "number of stress runs") DEFINE_bool(optimize_closures, true, "optimize closures") // assembler-ia32.cc / assembler-arm.cc / assembler-x64.cc +DEFINE_bool(hardfloat, false, + "use hardware floating point ABI") DEFINE_bool(debug_code, false, "generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false, "emit comments in code disassembly") diff --git a/tools/test.py b/tools/test.py index c1840bb42..fb0939170 100755 --- a/tools/test.py +++ b/tools/test.py @@ -1229,6 +1229,8 @@ def BuildOptions(): default=1, type="int") result.add_option("--noprof", help="Disable profiling support", default=False) + result.add_option("--hardfloat", help="use hardware floating point ABI", + default=False, action="store_true") return result @@ -1271,6 +1273,11 @@ def ProcessOptions(options): if options.noprof: options.scons_flags.append("prof=off") options.scons_flags.append("profilingsupport=off") + if options.hardfloat: + if options.special_command: + options.special_command += " --hardfloat" + else: + options.special_command = "@--hardfloat" return True -- 2.34.1