Revision: 7693
Author: [email protected]
Date: Wed Apr 27 07:29:25 2011
Log: Implement hardfloat calling convention in macro assembler and
simulator.
Review URL: http://codereview.chromium.org/6874007
http://code.google.com/p/v8/source/detail?r=7693
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/simulator-arm.cc
/branches/bleeding_edge/src/arm/simulator-arm.h
/branches/bleeding_edge/src/assembler.cc
/branches/bleeding_edge/src/assembler.h
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/tools/test.py
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue Apr 26 09:40:20
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Apr 27 07:29:25
2011
@@ -830,14 +830,26 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 =
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Apr 27
04:41:42 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Apr 27
07:29:25 2011
@@ -1345,11 +1345,11 @@
// 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 @@
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 @@
// 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);
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Apr 19
09:04:49 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Apr 27
07:29:25 2011
@@ -284,6 +284,15 @@
mov(dst, 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,
@@ -839,7 +848,11 @@
}
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 @@
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.
@@ -2812,27 +2849,94 @@
sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
}
}
+
+
+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 @@
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 {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue Apr 19
09:04:49 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Apr 27
07:29:25 2011
@@ -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 @@
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 @@
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 @@
// 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 @@
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);
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Mon Apr 18 06:53:11
2011
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Wed Apr 27 07:29:25
2011
@@ -1009,26 +1009,74 @@
}
-// 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 @@
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 @@
}
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);
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.h Mon Apr 18 06:53:11 2011
+++ /branches/bleeding_edge/src/arm/simulator-arm.h Wed Apr 27 07:29:25 2011
@@ -310,9 +310,10 @@
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();
=======================================
--- /branches/bleeding_edge/src/assembler.cc Tue Apr 19 09:04:49 2011
+++ /branches/bleeding_edge/src/assembler.cc Wed Apr 27 07:29:25 2011
@@ -887,7 +887,7 @@
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_sin_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
@@ -895,7 +895,7 @@
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_cos_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
@@ -903,7 +903,7 @@
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(math_log_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_CALL));
}
@@ -946,7 +946,7 @@
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(power_double_double),
- FP_RETURN_CALL));
+ BUILTIN_FP_FP_CALL));
}
@@ -954,7 +954,7 @@
Isolate* isolate) {
return ExternalReference(Redirect(isolate,
FUNCTION_ADDR(power_double_int),
- FP_RETURN_CALL));
+ BUILTIN_FP_INT_CALL));
}
@@ -987,17 +987,16 @@
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));
}
=======================================
--- /branches/bleeding_edge/src/assembler.h Tue Apr 19 09:04:49 2011
+++ /branches/bleeding_edge/src/assembler.h Wed Apr 27 07:29:25 2011
@@ -501,9 +501,21 @@
// 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&)
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Tue Apr 26 02:44:55 2011
+++ /branches/bleeding_edge/src/flag-definitions.h Wed Apr 27 07:29:25 2011
@@ -144,6 +144,8 @@
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")
=======================================
--- /branches/bleeding_edge/tools/test.py Mon Apr 18 00:23:48 2011
+++ /branches/bleeding_edge/tools/test.py Wed Apr 27 07:29:25 2011
@@ -1229,6 +1229,8 @@
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 @@
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
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev