Index: runtime/vm/simulator_arm.cc |
=================================================================== |
--- runtime/vm/simulator_arm.cc (revision 23860) |
+++ runtime/vm/simulator_arm.cc (working copy) |
@@ -801,13 +801,16 @@ |
Simulator::CallKind call_kind() const { return call_kind_; } |
+ int argument_count() const { return argument_count_; } |
+ |
static Redirection* Get(uword external_function, |
- Simulator::CallKind call_kind) { |
+ Simulator::CallKind call_kind, |
+ int argument_count) { |
Redirection* current; |
for (current = list_; current != NULL; current = current->next_) { |
if (current->external_function_ == external_function) return current; |
} |
- return new Redirection(external_function, call_kind); |
+ return new Redirection(external_function, call_kind, argument_count); |
} |
static Redirection* FromSvcInstruction(Instr* svc_instruction) { |
@@ -820,9 +823,12 @@ |
private: |
static const int32_t kRedirectSvcInstruction = |
((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode); |
- Redirection(uword external_function, Simulator::CallKind call_kind) |
+ Redirection(uword external_function, |
+ Simulator::CallKind call_kind, |
+ int argument_count) |
: external_function_(external_function), |
call_kind_(call_kind), |
+ argument_count_(argument_count), |
svc_instruction_(kRedirectSvcInstruction), |
next_(list_) { |
list_ = this; |
@@ -830,6 +836,7 @@ |
uword external_function_; |
Simulator::CallKind call_kind_; |
+ int argument_count_; |
uint32_t svc_instruction_; |
Redirection* next_; |
static Redirection* list_; |
@@ -839,8 +846,11 @@ |
Redirection* Redirection::list_ = NULL; |
-uword Simulator::RedirectExternalReference(uword function, CallKind call_kind) { |
- Redirection* redirection = Redirection::Get(function, call_kind); |
+uword Simulator::RedirectExternalReference(uword function, |
+ CallKind call_kind, |
+ int argument_count) { |
+ Redirection* redirection = |
+ Redirection::Get(function, call_kind, argument_count); |
return redirection->address_of_svc_instruction(); |
} |
@@ -1430,6 +1440,9 @@ |
typedef int32_t (*SimulatorLeafRuntimeCall)( |
int32_t r0, int32_t r1, int32_t r2, int32_t r3); |
+// Calls to leaf float Dart runtime functions are based on this interface. |
+typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
+ |
// Calls to native Dart functions are based on this interface. |
typedef void (*SimulatorNativeCall)(NativeArguments* arguments); |
@@ -1448,7 +1461,8 @@ |
OS::Print("Call to host function at 0x%"Pd"\n", external); |
} |
- if (redirection->call_kind() != kLeafRuntimeCall) { |
+ if ((redirection->call_kind() == kRuntimeCall) || |
+ (redirection->call_kind() == kNativeCall)) { |
// The top_exit_frame_info of the current isolate points to the top of |
// the simulator stack. |
ASSERT((StackTop() - Isolate::Current()->top_exit_frame_info()) < |
@@ -1468,6 +1482,8 @@ |
target(arguments); |
set_register(R0, icount_); // Zap result register from void function. |
} else if (redirection->call_kind() == kLeafRuntimeCall) { |
+ ASSERT((0 <= redirection->argument_count()) && |
+ (redirection->argument_count() <= 4)); |
int32_t r0 = get_register(R0); |
int32_t r1 = get_register(R1); |
int32_t r2 = get_register(R2); |
@@ -1476,6 +1492,19 @@ |
reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
r0 = target(r0, r1, r2, r3); |
set_register(R0, r0); // Set returned result from function. |
+ } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
+ ASSERT((0 <= redirection->argument_count()) && |
+ (redirection->argument_count() <= 2)); |
+ // We currently use 'hardfp' ('gnueabihf') rather than 'softfp' |
+ // ('gnueabi') float ABI for leaf runtime calls, i.e. double values |
+ // are passed and returned in vfp registers rather than in integer |
+ // register pairs. |
+ SimulatorLeafFloatRuntimeCall target = |
+ reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
+ double d0 = get_dregister(D0); |
+ double d1 = get_dregister(D1); |
+ d0 = target(d0, d1); |
+ set_dregister(D0, d0); |
} else { |
ASSERT(redirection->call_kind() == kNativeCall); |
NativeArguments* arguments; |
@@ -1495,10 +1524,11 @@ |
set_register(IP, icount_); |
set_register(LR, icount_); |
double zap_dvalue = static_cast<double>(icount_); |
- for (int i = D0; i <= D7; i++) { |
+ // Do not zap D0, as it may contain a float result. |
+ for (int i = D1; i <= D7; i++) { |
set_dregister(static_cast<DRegister>(i), zap_dvalue); |
} |
- // The above loop also zaps overlapping registers S0-S15. |
+ // The above loop also zaps overlapping registers S2-S15. |
// Registers D8-D15 (overlapping with S16-S31) are preserved. |
#ifdef VFPv3_D32 |
for (int i = D16; i <= D31; i++) { |