| Index: runtime/vm/simulator_mips.cc
|
| ===================================================================
|
| --- runtime/vm/simulator_mips.cc (revision 24063)
|
| +++ runtime/vm/simulator_mips.cc (working copy)
|
| @@ -92,6 +92,7 @@
|
|
|
| bool GetValue(char* desc, uint32_t* value);
|
| bool GetFValue(char* desc, double* value);
|
| + bool GetDValue(char* desc, double* value);
|
|
|
| // Set or delete a breakpoint. Returns true if successful.
|
| bool SetBreakpoint(Instr* breakpc);
|
| @@ -226,6 +227,26 @@
|
| }
|
|
|
|
|
| +bool SimulatorDebugger::GetDValue(char* desc, double* value) {
|
| + FRegister freg = LookupFRegisterByName(desc);
|
| + if (freg != kNoFRegister) {
|
| + *value = sim_->get_fregister_double(freg);
|
| + return true;
|
| + }
|
| + if (desc[0] == '*') {
|
| + uint32_t addr;
|
| + if (GetValue(desc + 1, &addr)) {
|
| + if (Simulator::IsIllegalAddress(addr)) {
|
| + return false;
|
| + }
|
| + *value = *(reinterpret_cast<double*>(addr));
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
|
| // Check if a breakpoint can be set. If not return without any side-effects.
|
| if (sim_->break_pc_ != NULL) {
|
| @@ -361,6 +382,20 @@
|
| } else {
|
| OS::Print("printfloat <dreg or *addr>\n");
|
| }
|
| + } else if ((strcmp(cmd, "pd") == 0) ||
|
| + (strcmp(cmd, "printdouble") == 0)) {
|
| + if (args == 2) {
|
| + double dvalue;
|
| + if (GetDValue(arg1, &dvalue)) {
|
| + uint64_t long_value = bit_cast<uint64_t, double>(dvalue);
|
| + OS::Print("%s: %llu 0x%llx %.8g\n",
|
| + arg1, long_value, long_value, dvalue);
|
| + } else {
|
| + OS::Print("%s unrecognized\n", arg1);
|
| + }
|
| + } else {
|
| + OS::Print("printfloat <dreg or *addr>\n");
|
| + }
|
| } else if ((strcmp(cmd, "po") == 0) ||
|
| (strcmp(cmd, "printobject") == 0)) {
|
| if (args == 2) {
|
| @@ -589,13 +624,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* FromBreakInstruction(Instr* break_instruction) {
|
| @@ -609,9 +647,12 @@
|
| static const int32_t kRedirectInstruction =
|
| Instr::kBreakPointInstruction | (Instr::kRedirectCode << kBreakCodeShift);
|
|
|
| - 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),
|
| break_instruction_(kRedirectInstruction),
|
| next_(list_) {
|
| list_ = this;
|
| @@ -619,6 +660,7 @@
|
|
|
| uword external_function_;
|
| Simulator::CallKind call_kind_;
|
| + int argument_count_;
|
| uint32_t break_instruction_;
|
| Redirection* next_;
|
| static Redirection* list_;
|
| @@ -628,8 +670,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_break_instruction();
|
| }
|
|
|
| @@ -890,6 +935,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);
|
|
|
| @@ -925,7 +973,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()) <
|
| @@ -953,6 +1002,17 @@
|
| reinterpret_cast<SimulatorLeafRuntimeCall>(external);
|
| a0 = target(a0, a1, a2, a3);
|
| set_register(V0, a0); // Set returned result from function.
|
| + } else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
|
| + ASSERT((0 <= redirection->argument_count()) &&
|
| + (redirection->argument_count() <= 2));
|
| + // double values are passed and returned in floating point registers.
|
| + SimulatorLeafFloatRuntimeCall target =
|
| + reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external);
|
| + double d0 = 0.0;
|
| + double d6 = get_fregister_double(F12);
|
| + double d7 = get_fregister_double(F14);
|
| + d0 = target(d6, d7);
|
| + set_fregister_double(F0, d0);
|
| } else {
|
| ASSERT(redirection->call_kind() == kNativeCall);
|
| NativeArguments* arguments;
|
| @@ -986,7 +1046,7 @@
|
|
|
| // Zap floating point registers.
|
| int32_t zap_dvalue = icount_;
|
| - for (int i = F0; i <= F31; i++) {
|
| + for (int i = F4; i <= F18; i++) {
|
| set_fregister(static_cast<FRegister>(i), zap_dvalue);
|
| }
|
|
|
| @@ -1109,6 +1169,20 @@
|
| set_register(instr->RdField(), get_lo_register());
|
| break;
|
| }
|
| + case MOVCI: {
|
| + ASSERT(instr->SaField() == 0);
|
| + ASSERT(instr->Bit(17) == 0);
|
| + int32_t rs_val = get_register(instr->RsField());
|
| + uint32_t cc, fcsr_cc, test, status;
|
| + cc = instr->Bits(18, 3);
|
| + fcsr_cc = get_fcsr_condition_bit(cc);
|
| + test = instr->Bit(16);
|
| + status = test_fcsr_bit(fcsr_cc);
|
| + if (test == status) {
|
| + set_register(instr->RdField(), rs_val);
|
| + }
|
| + break;
|
| + }
|
| case MOVN: {
|
| ASSERT(instr->SaField() == 0);
|
| // Format(instr, "movn 'rd, 'rs, 'rt");
|
| @@ -1520,6 +1594,12 @@
|
| set_fregister_double(instr->FdField(), fs_dbl);
|
| break;
|
| }
|
| + case FMT_S: {
|
| + float fs_flt = get_fregister_float(instr->FsField());
|
| + double fs_dbl = static_cast<double>(fs_flt);
|
| + set_fregister_double(instr->FdField(), fs_dbl);
|
| + break;
|
| + }
|
| case FMT_L: {
|
| int64_t fs_int = get_fregister_long(instr->FsField());
|
| double fs_dbl = static_cast<double>(fs_int);
|
|
|