// 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);
// 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.
}
}
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();
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,
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,
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 =
// 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()));
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());
// 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);
}
+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() &&
}
void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
- vmov(dst, r0, r1);
+ if (FLAG_hardfloat) {
+ Move(dst, d0);
+ } else {
+ vmov(dst, r0, r1);
+ }
}
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.
}
+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.
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:
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.
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
// 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);
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);
}
-// 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));
+ }
}
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));
}
}
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);
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();
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_sin_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_cos_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_log_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(power_double_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_FP_CALL));
}
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(power_double_int),
- FP_RETURN_CALL));
+ BUILTIN_FP_INT_CALL));
}
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));
}
// 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&)
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")
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
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