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
parent 145ec569
......@@ -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 =
......
......@@ -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);
......
......@@ -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 {
......
// 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<Object> 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<Label*> 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);
......
......@@ -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);
......
......@@ -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();
......
......@@ -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));
}
......
......@@ -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<Value> f(v8::Arguments&)
......
......@@ -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")
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment