Enables language tests for SIMMIPS.

R=regis@google.com

Review URL: https://codereview.chromium.org//17131002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@24098 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 8f43046..f4f3de1 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -346,14 +346,14 @@
     // Setup pool pointer for this stub.
     Label next;
     bal(&next);
-    delay_slot()->mov(T0, RA);
+    delay_slot()->mov(TMP1, RA);
 
     const intptr_t object_pool_pc_dist =
         Instructions::HeaderSize() - Instructions::object_pool_offset() +
         CodeSize();
 
     Bind(&next);
-    lw(PP, Address(T0, -object_pool_pc_dist));
+    lw(PP, Address(TMP1, -object_pool_pc_dist));
   } else {
     addiu(SP, SP, Immediate(-3 * kWordSize));
     sw(ZR, Address(SP, 2 * kWordSize));  // PC marker is 0 in stubs.
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 9b22f3e..0b74365 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -67,6 +67,9 @@
     return Utils::IsInt(kImmBits, offset);
   }
 
+  Register base() const { return base_; }
+  int32_t offset() const { return offset_; }
+
  private:
   Register base_;
   int32_t offset_;
@@ -439,6 +442,12 @@
     EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ);
   }
 
+  // Convert a 32-bit float in fs to a 64-bit double in dd.
+  void cvtds(DRegister dd, FRegister fs) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_CVT_D);
+  }
+
   // Converts a 32-bit signed int in fs to a double in fd.
   void cvtdw(DRegister dd, FRegister fs) {
     FRegister fd = static_cast<FRegister>(dd * 2);
@@ -553,10 +562,20 @@
     EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV);
   }
 
+  // Move if floating point false.
+  void movf(Register rd, Register rs) {
+    EmitRType(SPECIAL, rs, R0, rd, 0, MOVCI);
+  }
+
   void movn(Register rd, Register rs, Register rt) {
     EmitRType(SPECIAL, rs, rt, rd, 0, MOVN);
   }
 
+  // Move if floating point true.
+  void movt(Register rd, Register rs) {
+    EmitRType(SPECIAL, rs, R1, rd, 0, MOVCI);
+  }
+
   void movz(Register rd, Register rs, Register rt) {
     EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ);
   }
@@ -972,6 +991,20 @@
     sra(reg, reg, kSmiTagSize);
   }
 
+  void StoreDToOffset(DRegister reg, Register base, int32_t offset) {
+    FRegister lo = static_cast<FRegister>(reg * 2);
+    FRegister hi = static_cast<FRegister>(reg * 2 + 1);
+    swc1(lo, Address(base, offset));
+    swc1(hi, Address(base, offset + kWordSize));
+  }
+
+  void LoadDFromOffset(DRegister reg, Register base, int32_t offset) {
+    FRegister lo = static_cast<FRegister>(reg * 2);
+    FRegister hi = static_cast<FRegister>(reg * 2 + 1);
+    lwc1(lo, Address(base, offset));
+    lwc1(hi, Address(base, offset + kWordSize));
+  }
+
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
   // Create a frame for calling into runtime that preserves all volatile
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc
index 96088fd..5cd9108 100644
--- a/runtime/vm/code_patcher_mips.cc
+++ b/runtime/vm/code_patcher_mips.cc
@@ -47,7 +47,9 @@
 
 
 void CodePatcher::InsertCallAt(uword start, uword target) {
-  UNIMPLEMENTED();
+  // The inserted call should not overlap the lazy deopt jump code.
+  ASSERT(start + CallPattern::kFixedLengthInBytes <= target);
+  CallPattern::InsertAt(start, target);
 }
 
 
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index e016f7b..b1f910a 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -156,9 +156,13 @@
   kNoDRegister = -1,
 };
 
+const DRegister DTMP = D9;
+const FRegister STMP1 = F18;
+const FRegister STMP2 = F19;
+
 // Architecture independent aliases.
 typedef DRegister FpuRegister;
-const FpuRegister FpuTMP = D0;
+const FpuRegister FpuTMP = DTMP;
 const int kNumberOfFpuRegisters = kNumberOfDRegisters;
 const FpuRegister kNoFpuRegister = kNoDRegister;
 
@@ -172,13 +176,6 @@
 const Register SPREG = SP;  // Stack pointer register.
 const Register FPREG = FP;  // Frame pointer register.
 
-// NULLREG holds reinterpret_cast<intptr_t>(Object::null()).
-// TODO(zra): Is it worthwhile to devote a register to this? Investigate
-// performance effects when we are running on real hardware. Same with
-// CMPRES. Try moving CTX and PP to T8 and T9 and shifting kLastCpuRegister
-// down to S7.
-const Register NULLREG = T8;
-
 // The code that generates a comparison can be far away from the code that
 // generates the branch that uses the result of that comparison. In this case,
 // CMPRES is used for the result of the comparison.
diff --git a/runtime/vm/debugger_mips.cc b/runtime/vm/debugger_mips.cc
index c35df1b..a8721ac 100644
--- a/runtime/vm/debugger_mips.cc
+++ b/runtime/vm/debugger_mips.cc
@@ -48,7 +48,6 @@
   Instr* instr5 = Instr::At(pc_ - 1 * Instr::kInstrSize);
 
 #if defined(DEBUG)
-
   instr1->AssertIsImmInstr(LW, SP, RA, 2 * kWordSize);
   instr2->AssertIsImmInstr(LW, SP, FP, 1 * kWordSize);
   instr3->AssertIsImmInstr(LW, SP, PP, 0 * kWordSize);
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index ecbea4f..e97b981 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -329,6 +329,14 @@
       Format(instr, "mflo 'rd");
       break;
     }
+    case MOVCI: {
+      if (instr->Bit(16)) {
+        Format(instr, "movt 'rd, 'rs");
+      } else {
+        Format(instr, "movf 'rd, 'rs");
+      }
+      break;
+    }
     case MOVN: {
       Format(instr, "movn 'rd, 'rs, 'rt");
       break;
@@ -523,35 +531,35 @@
         break;
       }
       case COP1_C_F: {
-        Format(instr, "c.f.'fmt 'fd, 'fs");
+        Format(instr, "c.f.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_UN: {
-        Format(instr, "c.un.'fmt 'fd, 'fs");
+        Format(instr, "c.un.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_EQ: {
-        Format(instr, "c.eq.'fmt 'fd, 'fs");
+        Format(instr, "c.eq.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_UEQ: {
-        Format(instr, "c.ueq.'fmt 'fd, 'fs");
+        Format(instr, "c.ueq.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_OLT: {
-        Format(instr, "c.olt.'fmt 'fd, 'fs");
+        Format(instr, "c.olt.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_ULT: {
-        Format(instr, "c.ult.'fmt 'fd, 'fs");
+        Format(instr, "c.ult.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_OLE: {
-        Format(instr, "c.ole.'fmt 'fd, 'fs");
+        Format(instr, "c.ole.'fmt 'fs, 'ft");
         break;
       }
       case COP1_C_ULE: {
-        Format(instr, "c.ule.'fmt 'fd, 'fs");
+        Format(instr, "c.ule.'fmt 'fs, 'ft");
         break;
       }
       case COP1_CVT_D: {
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 27abae0..a088cc6 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -166,7 +166,8 @@
                                            Label* is_false) {
   __ TraceSimMsg("BoolToJump");
   Label fall_through;
-  __ beq(bool_register, NULLREG, &fall_through);
+  __ BranchEqual(bool_register, reinterpret_cast<int32_t>(Object::null()),
+                 &fall_through);
   __ BranchEqual(bool_register, Bool::True(), is_true);
   __ b(is_false);
   __ Bind(&fall_through);
@@ -190,12 +191,12 @@
   __ LoadObject(A2, type_test_cache);
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
+    __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
     __ BranchLink(&StubCode::Subtype1TestCacheLabel());
-    __ delay_slot()->mov(A1, NULLREG);
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
+    __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
     __ BranchLink(&StubCode::Subtype2TestCacheLabel());
-    __ delay_slot()->mov(A1, NULLREG);
   } else if (test_kind == kTestTypeThreeArgs) {
     ASSERT(type_arguments_reg == A1);
     __ BranchLink(&StubCode::Subtype3TestCacheLabel());
@@ -329,7 +330,8 @@
     // Check if instance is a closure.
     __ LoadClassById(T1, kClassIdReg);
     __ lw(T1, FieldAddress(T1, Class::signature_function_offset()));
-    __ bne(T1, NULLREG, is_instance_lbl);
+    __ BranchNotEqual(T1, reinterpret_cast<int32_t>(Object::null()),
+                      is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -397,7 +399,8 @@
     __ lw(A1, Address(SP, 0));  // Get instantiator type arguments.
     // A1: instantiator type arguments.
     // Check if type argument is dynamic.
-    __ beq(A1, NULLREG, is_instance_lbl);
+    __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+    __ beq(A1, T7, is_instance_lbl);
     // Can handle only type arguments that are instances of TypeArguments.
     // (runtime checks canonicalize type arguments).
     Label fall_through;
@@ -408,7 +411,7 @@
     // R2: concrete type of type.
     // Check if type argument is dynamic.
     __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
-    __ beq(T2, NULLREG, is_instance_lbl);
+    __ beq(T2, T7, is_instance_lbl);
     const Type& object_type = Type::ZoneHandle(Type::ObjectType());
     __ BranchEqual(T2, object_type, is_instance_lbl);
 
@@ -483,11 +486,11 @@
   if (TypeCheckAsClassEquality(type)) {
     const intptr_t type_cid = Class::Handle(type.type_class()).id();
     const Register kInstanceReg = A0;
-    __ andi(T0, kInstanceReg, Immediate(kSmiTagMask));
+    __ andi(CMPRES, kInstanceReg, Immediate(kSmiTagMask));
     if (type_cid == kSmiCid) {
-      __ beq(T0, ZR, is_instance_lbl);
+      __ beq(CMPRES, ZR, is_instance_lbl);
     } else {
-      __ beq(T0, ZR, is_not_instance_lbl);
+      __ beq(CMPRES, ZR, is_not_instance_lbl);
       __ LoadClassId(T0, kInstanceReg);
       __ BranchEqual(T0, type_cid, is_instance_lbl);
     }
@@ -527,12 +530,90 @@
 }
 
 
+// If instanceof type test cannot be performed successfully at compile time and
+// therefore eliminated, optimize it by adding inlined tests for:
+// - NULL -> return false.
+// - Smi -> compile time subtype check (only if dst class is not parameterized).
+// - Class equality (only if class is not parameterized).
+// Inputs:
+// - A0: object.
+// - A1: instantiator type arguments or raw_null.
+// - A2: instantiator or raw_null.
+// Returns:
+// - true or false in V0.
 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
                                            intptr_t deopt_id,
                                            const AbstractType& type,
                                            bool negate_result,
                                            LocationSummary* locs) {
-  UNIMPLEMENTED();
+  ASSERT(type.IsFinalized() && !type.IsMalformed());
+
+  // Preserve instantiator (A2) and its type arguments (A1).
+  __ addiu(SP, SP, Immediate(-2 * kWordSize));
+  __ sw(A2, Address(SP, 1 * kWordSize));
+  __ sw(A1, Address(SP, 0 * kWordSize));
+
+  Label is_instance, is_not_instance;
+  // If type is instantiated and non-parameterized, we can inline code
+  // checking whether the tested instance is a Smi.
+  if (type.IsInstantiated()) {
+    // A null object is only an instance of Object and dynamic, which has
+    // already been checked above (if the type is instantiated). So we can
+    // return false here if the instance is null (and if the type is
+    // instantiated).
+    // We can only inline this null check if the type is instantiated at compile
+    // time, since an uninstantiated type at compile time could be Object or
+    // dynamic at run time.
+    __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()),
+                   &is_not_instance);
+  }
+
+  // Generate inline instanceof test.
+  SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+  test_cache = GenerateInlineInstanceof(token_pos, type,
+                                        &is_instance, &is_not_instance);
+
+  // test_cache is null if there is no fall-through.
+  Label done;
+  if (!test_cache.IsNull()) {
+    // Generate runtime call.
+    // Load instantiator (A2) and its type arguments (A1).
+    __ lw(A1, Address(SP, 0 * kWordSize));
+    __ lw(A2, Address(SP, 1 * kWordSize));
+
+    __ addiu(SP, SP, Immediate(-6 * kWordSize));
+    __ LoadObject(TMP, Object::ZoneHandle());
+    __ sw(TMP, Address(SP, 5 * kWordSize));  // Make room for the result.
+    __ sw(A0, Address(SP, 4 * kWordSize));  // Push the instance.
+    __ LoadObject(TMP, type);
+    __ sw(TMP, Address(SP, 3 * kWordSize));  // Push the type.
+    __ sw(A2, Address(SP, 2 * kWordSize));  // Push instantiator.
+    __ sw(A1, Address(SP, 1 * kWordSize));  // Push type arguments.
+    __ LoadObject(A0, test_cache);
+    __ sw(A0, Address(SP, 0 * kWordSize));
+    GenerateCallRuntime(token_pos, deopt_id, kInstanceofRuntimeEntry, locs);
+    // Pop the parameters supplied to the runtime entry. The result of the
+    // instanceof runtime call will be left as the result of the operation.
+    __ lw(T0, Address(SP, 5 * kWordSize));
+    __ addiu(SP, SP, Immediate(6 * kWordSize));
+    if (negate_result) {
+      __ LoadObject(V0, Bool::True());
+      __ bne(T0, V0, &done);
+      __ LoadObject(V0, Bool::False());
+    } else {
+      __ mov(V0, T0);
+    }
+    __ b(&done);
+  }
+  __ Bind(&is_not_instance);
+  __ LoadObject(V0, negate_result ? Bool::True() : Bool::False());
+  __ b(&done);
+
+  __ Bind(&is_instance);
+  __ LoadObject(V0, negate_result ? Bool::False() : Bool::True());
+  __ Bind(&done);
+  // Remove instantiator (A2) and its type arguments (A1).
+  __ Drop(2);
 }
 
 
@@ -567,7 +648,8 @@
 
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
-  __ beq(A0, NULLREG, &is_assignable);
+
+  __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable);
   __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
 
   if (!FLAG_eliminate_type_checks) {
@@ -804,7 +886,8 @@
     delete[] opt_param_position;
     // Check that T0 now points to the null terminator in the array descriptor.
     __ lw(T3, Address(T0));
-    __ beq(T3, NULLREG, &all_arguments_processed);
+    __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()),
+                   &all_arguments_processed);
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ Comment("There are optional positional parameters");
@@ -894,8 +977,9 @@
   __ Bind(&null_args_loop);
   __ addiu(T2, T2, Immediate(-kWordSize));
   __ addu(T3, T1, T2);
+  __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
   __ bgtz(T2, &null_args_loop);
-  __ delay_slot()->sw(NULLREG, Address(T3));
+  __ delay_slot()->sw(TMP, Address(T3));
   __ Bind(&null_args_loop_exit);
 }
 
@@ -918,8 +1002,9 @@
   __ lw(T0, Address(SP, 1 * kWordSize));  // Receiver.
   __ lw(T1, Address(SP, 0 * kWordSize));  // Value.
   __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
+  __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
   __ Ret();
-  __ delay_slot()->mov(V0, NULLREG);
+  __ delay_slot()->mov(V0, TMP);
 }
 
 
@@ -1113,7 +1198,8 @@
     const intptr_t slot_base = parsed_function().first_stack_local_index();
     for (intptr_t i = 0; i < num_locals; ++i) {
       // Subtract index i (locals lie at lower addresses than FP).
-      __ sw(NULLREG, Address(FP, (slot_base - i) * kWordSize));
+      __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+      __ sw(TMP, Address(FP, (slot_base - i) * kWordSize));
     }
   }
 
@@ -1348,11 +1434,11 @@
     __ addiu(SP, SP, Immediate(-2 * kWordSize));
     __ sw(reg, Address(SP, 1 * kWordSize));
     __ LoadObject(TMP1, obj);
+    __ sw(TMP1, Address(SP, 0 * kWordSize));
     __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
-    __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize));
     __ TraceSimMsg("EqualityRegConstCompare return");
     __ lw(reg, Address(SP, 1 * kWordSize));  // Restore 'reg'.
     __ addiu(SP, SP, Immediate(2 * kWordSize));  // Discard constant.
@@ -1367,14 +1453,15 @@
                                                   bool needs_number_check,
                                                   intptr_t token_pos) {
   __ TraceSimMsg("EqualityRegRegCompare");
+  __ Comment("EqualityRegRegCompare");
   if (needs_number_check) {
     __ addiu(SP, SP, Immediate(-2 * kWordSize));
     __ sw(left, Address(SP, 1 * kWordSize));
+    __ sw(right, Address(SP, 0 * kWordSize));
     __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
-    __ delay_slot()->sw(right, Address(SP, 0 * kWordSize));
     __ TraceSimMsg("EqualityRegRegCompare return");
     // Stub returns result in CMPRES. If it is 0, then left and right are equal.
     __ lw(right, Address(SP, 0 * kWordSize));
@@ -1395,8 +1482,9 @@
   __ TraceSimMsg("SuperEqualityCallPrologue");
   __ lw(result, Address(SP, 0 * kWordSize));  // Load right operand.
   __ lw(TMP1, Address(SP, 1 * kWordSize));  // Load left operand.
-  __ beq(result, NULLREG, &check_identity);  // Is right null?
-  __ bne(TMP1, NULLREG, &fall_through);  // If right is non-null, check left.
+  __ LoadImmediate(CMPRES, reinterpret_cast<int32_t>(Object::null()));
+  __ beq(result, CMPRES, &check_identity);  // Is right null?
+  __ bne(TMP1, CMPRES, &fall_through);  // If right is non-null, check left.
 
   __ Bind(&check_identity);
   __ bne(result, TMP1, &is_false);
@@ -1414,9 +1502,20 @@
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
   __ TraceSimMsg("SaveLiveRegisters");
   // TODO(vegorov): consider saving only caller save (volatile) registers.
-  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
-  if (fpu_registers > 0) {
-    UNIMPLEMENTED();
+  const intptr_t fpu_regs_count= locs->live_registers()->fpu_regs_count();
+  if (fpu_regs_count > 0) {
+    __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize));
+    // Store fpu registers with the lowest register number at the lowest
+    // address.
+    intptr_t offset = 0;
+    for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
+      DRegister fpu_reg = static_cast<DRegister>(reg_idx);
+      if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
+        __ StoreDToOffset(fpu_reg, SP, offset);
+        offset += kFpuRegisterSize;
+      }
+    }
+    ASSERT(offset == (fpu_regs_count * kFpuRegisterSize));
   }
 
   // Store general purpose registers with the lowest register number at the
@@ -1455,9 +1554,19 @@
   }
   __ addiu(SP, SP, Immediate(register_count * kWordSize));
 
-  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
-  if (fpu_registers > 0) {
-    UNIMPLEMENTED();
+  const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count();
+  if (fpu_regs_count > 0) {
+    // Fpu registers have the lowest register number at the lowest address.
+    intptr_t offset = 0;
+    for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
+      DRegister fpu_reg = static_cast<DRegister>(reg_idx);
+      if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
+        __ LoadDFromOffset(fpu_reg, SP, offset);
+        offset += kFpuRegisterSize;
+      }
+    }
+    ASSERT(offset == (fpu_regs_count * kFpuRegisterSize));
+    __ AddImmediate(SP, offset);
   }
 }
 
@@ -1481,6 +1590,7 @@
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   __ TraceSimMsg("EmitTestAndCall");
+  __ Comment("EmitTestAndCall");
   __ LoadObject(S4, arguments_descriptor);
   for (intptr_t i = 0; i < len; i++) {
     const bool is_last_check = (i == (len - 1));
@@ -1513,7 +1623,33 @@
                                                 FpuRegister left,
                                                 FpuRegister right,
                                                 BranchInstr* branch) {
-  UNIMPLEMENTED();
+  ASSERT(branch != NULL);
+  __ Comment("DoubleCompareBranch");
+  assembler()->cund(left, right);
+  BlockEntryInstr* nan_result = (true_condition == NE) ?
+      branch->true_successor() : branch->false_successor();
+  assembler()->bc1t(GetJumpLabel(nan_result));
+
+  switch (true_condition) {
+    case EQ: assembler()->ceqd(left, right); break;
+    case LT: assembler()->coltd(left, right); break;
+    case LE: assembler()->coled(left, right); break;
+    case GT: assembler()->coltd(right, left); break;
+    case GE: assembler()->coled(right, left); break;
+    default: {
+      // Should only passing the above conditions to this function.
+      UNREACHABLE();
+      break;
+    }
+  }
+
+  assembler()->LoadImmediate(TMP, 1);
+  assembler()->movf(CMPRES, TMP);
+  assembler()->movt(CMPRES, ZR);
+  assembler()->mov(TMP, ZR);
+
+  // EmitBranchOnCondition expects ordering to be described by CMPRES, TMP1.
+  branch->EmitBranchOnCondition(this, EQ);
 }
 
 
@@ -1521,7 +1657,28 @@
                                               FpuRegister left,
                                               FpuRegister right,
                                               Register result) {
-  UNIMPLEMENTED();
+  Label done;
+  __ Comment("DoubleCompareBool");
+  assembler()->LoadObject(result, Bool::False());
+  assembler()->cund(left, right);
+  assembler()->bc1t(&done);
+
+  switch (true_condition) {
+    case EQ: assembler()->ceqd(left, right); break;
+    case LT: assembler()->coltd(left, right); break;
+    case LE: assembler()->coled(left, right); break;
+    case GT: assembler()->coltd(right, left); break;
+    case GE: assembler()->coled(right, left); break;
+    default: {
+      // Should only passing the above conditions to this function.
+      UNREACHABLE();
+      break;
+    }
+  }
+
+  assembler()->bc1f(&done);  // False is already in result.
+  assembler()->LoadObject(result, Bool::True());
+  assembler()->Bind(&done);
 }
 
 
@@ -1591,7 +1748,9 @@
       __ movd(destination.fpu_reg(), source.fpu_reg());
     } else {
       if (destination.IsDoubleStackSlot()) {
-        __ sdc1(source.fpu_reg(), destination.ToStackSlotAddress());
+        const Address& addr = destination.ToStackSlotAddress();
+        int32_t offset = addr.offset();
+        __ StoreDToOffset(source.fpu_reg(), FP, offset);
       } else {
         ASSERT(destination.IsQuadStackSlot());
         UNIMPLEMENTED();
@@ -1599,11 +1758,18 @@
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
-      __ ldc1(destination.fpu_reg(), source.ToStackSlotAddress());
+      const Address &addr = source.ToStackSlotAddress();
+      const Register base = addr.base();
+      const int32_t offset = addr.offset();
+      __ LoadDFromOffset(destination.fpu_reg(), base, offset);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      __ ldc1(FpuTMP, source.ToStackSlotAddress());
-      __ sdc1(FpuTMP, destination.ToStackSlotAddress());
+      const Address& saddr = source.ToStackSlotAddress();
+      const Address& daddr = destination.ToStackSlotAddress();
+      int32_t soffset = saddr.offset();
+      int32_t doffset = daddr.offset();
+      __ LoadDFromOffset(FpuTMP, FP, soffset);
+      __ StoreDToOffset(FpuTMP, FP, doffset);
     }
   } else if (source.IsQuadStackSlot()) {
     UNIMPLEMENTED();
@@ -1658,8 +1824,10 @@
         : source.ToStackSlotAddress();
 
     if (double_width) {
-      __ ldc1(FpuTMP, slot_address);
-      __ sdc1(reg, slot_address);
+      const Register base = slot_address.base();
+      const int32_t offset = slot_address.offset();
+      __ LoadDFromOffset(FpuTMP, base, offset);
+      __ StoreDToOffset(reg, base, offset);
       __ movd(reg, FpuTMP);
     } else {
       UNIMPLEMENTED();
@@ -1667,12 +1835,16 @@
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
     const Address& source_slot_address = source.ToStackSlotAddress();
     const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const Register sbase = source_slot_address.base();
+    const int32_t soffset = source_slot_address.offset();
+    const Register dbase = destination_slot_address.base();
+    const int32_t doffset = destination_slot_address.offset();
 
     ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
-    __ ldc1(FpuTMP, source_slot_address);
-    __ ldc1(ensure_scratch.reg(), destination_slot_address);
-    __ sdc1(FpuTMP, destination_slot_address);
-    __ sdc1(ensure_scratch.reg(), source_slot_address);
+    __ LoadDFromOffset(FpuTMP, sbase, soffset);
+    __ LoadDFromOffset(ensure_scratch.reg(), dbase, doffset);
+    __ StoreDToOffset(FpuTMP, dbase, doffset);
+    __ StoreDToOffset(ensure_scratch.reg(), sbase, soffset);
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     UNIMPLEMENTED();
   } else {
@@ -1746,13 +1918,13 @@
 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
   __ TraceSimMsg("ParallelMoveResolver::SpillFpuScratch");
   __ AddImmediate(SP, -kDoubleSize);
-  __ sdc1(reg, Address(SP));
+  __ StoreDToOffset(reg, SP, 0);
 }
 
 
 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
   __ TraceSimMsg("ParallelMoveResolver::RestoreFpuScratch");
-  __ ldc1(reg, Address(SP));
+  __ LoadDFromOffset(reg, SP, 0);
   __ AddImmediate(SP, kDoubleSize);
 }
 
diff --git a/runtime/vm/instructions_mips.cc b/runtime/vm/instructions_mips.cc
index 41648b1..197efd1 100644
--- a/runtime/vm/instructions_mips.cc
+++ b/runtime/vm/instructions_mips.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_ARCH_MIPS)
 
 #include "vm/constants_mips.h"
+#include "vm/cpu.h"
 #include "vm/instructions.h"
 #include "vm/object.h"
 
@@ -158,6 +159,24 @@
 }
 
 
+void CallPattern::InsertAt(uword pc, uword target_address) {
+  Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize));
+  Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize));
+  Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize));
+  Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize));
+  uint16_t target_lo = target_address & 0xffff;
+  uint16_t target_hi = target_address >> 16;
+
+  lui->SetImmInstrBits(LUI, ZR, TMP1, target_hi);
+  ori->SetImmInstrBits(ORI, TMP1, TMP1, target_lo);
+  jr->SetSpecialInstrBits(JALR, TMP1, ZR, RA);
+  nop->SetInstructionBits(Instr::kNopInstruction);
+
+  ASSERT(kFixedLengthInBytes == 4 * Instr::kInstrSize);
+  CPU::FlushICache(pc, kFixedLengthInBytes);
+}
+
+
 JumpPattern::JumpPattern(uword pc) : pc_(pc) { }
 
 
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h
index 5567ae6..f9d7908 100644
--- a/runtime/vm/instructions_mips.h
+++ b/runtime/vm/instructions_mips.h
@@ -27,7 +27,9 @@
 
   // This constant length is only valid for inserted call patterns used for
   // lazy deoptimization. Regular call pattern may vary in length.
-  static const int kFixedLengthInBytes = 3 * Instr::kInstrSize;
+  static const int kFixedLengthInBytes = 4 * Instr::kInstrSize;
+
+  static void InsertAt(uword pc, uword target_address);
 
  private:
   uword Back(int n) const;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 8bf386e..813378d 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -387,11 +387,13 @@
   const int kNumArgumentsChecked = 2;
 
   __ TraceSimMsg("EmitEqualityAsInstanceCall");
+  __ Comment("EmitEqualityAsInstanceCall");
   Label check_identity;
   __ lw(A1, Address(SP, 1 * kWordSize));
   __ lw(A0, Address(SP, 0 * kWordSize));
-  __ beq(A1, NULLREG, &check_identity);
-  __ beq(A0, NULLREG, &check_identity);
+  __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+  __ beq(A1, TMP, &check_identity);
+  __ beq(A0, TMP, &check_identity);
 
   ICData& equality_ic_data = ICData::ZoneHandle();
   if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
@@ -536,6 +538,7 @@
   Register temp = locs->temp(0).reg();
 
   __ TraceSimMsg("EmitEqualityAsPolymorphicCall");
+  __ Comment("EmitEqualityAsPolymorphicCall");
 
   LoadValueCid(compiler, temp, left,
                (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
@@ -608,12 +611,57 @@
 
 // Emit code when ICData's targets are all Object == (which is ===).
 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
-                                   const ICData& ic_data,
+                                   const ICData& orig_ic_data,
                                    const LocationSummary& locs,
                                    Token::Kind kind,
                                    BranchInstr* branch,
                                    intptr_t deopt_id) {
-  UNIMPLEMENTED();
+  ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
+  Register left = locs.in(0).reg();
+  Register right = locs.in(1).reg();
+  Register temp = locs.temp(0).reg();
+  Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
+
+  __ Comment("CheckedStrictEqual");
+
+  __ andi(CMPRES, left, Immediate(kSmiTagMask));
+  __ beq(CMPRES, ZR, deopt);
+  // 'left' is not Smi.
+  Label identity_compare;
+  __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+  __ beq(right, TMP, &identity_compare);
+  __ beq(left, TMP, &identity_compare);
+
+  __ LoadClassId(temp, left);
+  const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
+  const intptr_t len = ic_data.NumberOfChecks();
+  for (intptr_t i = 0; i < len; i++) {
+    if (i == (len - 1)) {
+      __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt);
+    } else {
+      __ BranchEqual(temp, ic_data.GetReceiverClassIdAt(i), &identity_compare);
+    }
+  }
+  __ Bind(&identity_compare);
+  __ subu(CMPRES, left, right);
+  if (branch == NULL) {
+    Label done, is_equal;
+    Register result = locs.out().reg();
+    __ beq(CMPRES, ZR, &is_equal);
+    // Not equal.
+    __ LoadObject(result,
+                  (kind == Token::kEQ) ? Bool::False() : Bool::True());
+    __ b(&done);
+    __ Bind(&is_equal);
+    __ LoadObject(result,
+                  (kind == Token::kEQ) ? Bool::True() : Bool::False());
+    __ Bind(&done);
+
+  } else {
+    Condition cond = TokenKindToSmiCondition(kind);
+    __ mov(TMP, ZR);
+    branch->EmitBranchOnCondition(compiler, cond);
+  }
 }
 
 
@@ -633,8 +681,10 @@
   Register right = locs->in(1).reg();
   Label done, identity_compare, non_null_compare;
   __ TraceSimMsg("EmitGenericEqualityCompare");
-  __ beq(right, NULLREG, &identity_compare);
-  __ bne(left, NULLREG, &non_null_compare);
+  __ Comment("EmitGenericEqualityCompare");
+  __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+  __ beq(right, TMP, &identity_compare);
+  __ bne(left, TMP, &non_null_compare);
 
   // Comparison with NULL is "===".
   __ Bind(&identity_compare);
@@ -685,6 +735,7 @@
                                 Token::Kind kind,
                                 BranchInstr* branch) {
   __ TraceSimMsg("EmitSmiComparisonOp");
+  __ Comment("EmitSmiComparisonOp");
   Location left = locs.in(0);
   Location right = locs.in(1);
   ASSERT(!left.IsConstant() || !right.IsConstant());
@@ -732,17 +783,45 @@
 }
 
 
+static Condition TokenKindToDoubleCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ: return EQ;
+    case Token::kNE: return NE;
+    case Token::kLT: return LT;
+    case Token::kGT: return GT;
+    case Token::kLTE: return LE;
+    case Token::kGTE: return GE;
+    default:
+      UNREACHABLE();
+      return VS;
+  }
+}
+
+
 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
                                    const LocationSummary& locs,
                                    Token::Kind kind,
                                    BranchInstr* branch) {
-  UNIMPLEMENTED();
+  DRegister left = locs.in(0).fpu_reg();
+  DRegister right = locs.in(1).fpu_reg();
+
+  __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right);
+
+  Condition true_condition = TokenKindToDoubleCondition(kind);
+  if (branch != NULL) {
+    compiler->EmitDoubleCompareBranch(
+        true_condition, left, right, branch);
+  } else {
+    compiler->EmitDoubleCompareBool(
+        true_condition, left, right, locs.out().reg());
+  }
 }
 
 
 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
   BranchInstr* kNoBranch = NULL;
+  __ Comment("EqualityCompareInstr");
   if (receiver_class_id() == kSmiCid) {
     EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
@@ -785,6 +864,7 @@
 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                           BranchInstr* branch) {
   __ TraceSimMsg("EqualityCompareInstr");
+  __ Comment("EqualityCompareInstr:BranchCode");
   ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
   if (receiver_class_id() == kSmiCid) {
     // Deoptimizes if both arguments not Smi.
@@ -1001,7 +1081,9 @@
   // into the runtime system.
   uword entry = reinterpret_cast<uword>(native_c_function());
 #if defined(USING_SIMULATOR)
-  entry = Simulator::RedirectExternalReference(entry, Simulator::kNativeCall);
+  entry = Simulator::RedirectExternalReference(entry,
+                                               Simulator::kNativeCall,
+                                               function().NumParameters());
 #endif
   __ LoadImmediate(T5, entry);
   __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function()));
@@ -1205,7 +1287,28 @@
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedMint) ||
       (representation() == kUnboxedFloat32x4)) {
-    UNIMPLEMENTED();
+    DRegister result = locs()->out().fpu_reg();
+    switch (class_id()) {
+      case kTypedDataInt32ArrayCid:
+        UNIMPLEMENTED();
+        break;
+      case kTypedDataUint32ArrayCid:
+        UNIMPLEMENTED();
+        break;
+      case kTypedDataFloat32ArrayCid:
+        // Load single precision float and promote to double.
+        __ lwc1(STMP1, element_address);
+        __ cvtds(result, STMP1);
+        break;
+      case kTypedDataFloat64ArrayCid:
+        __ LoadDFromOffset(result, index.reg(),
+            FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
+        break;
+      case kTypedDataFloat32x4ArrayCid:
+        UNIMPLEMENTED();
+        break;
+    }
+    return;
   }
 
   Register result = locs()->out().reg();
@@ -1582,7 +1685,8 @@
 
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ beq(CMPRES, ZR, &ok);
-        __ subu(CMPRES, value_reg, NULLREG);
+        __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+        __ subu(CMPRES, value_reg, TMP);
       }
 
       if (ok_is_fall_through) {
@@ -1703,13 +1807,30 @@
 
 
 LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(A0));
+  summary->set_in(1, Location::RegisterLocation(A2));
+  summary->set_in(2, Location::RegisterLocation(A1));
+  summary->set_out(Location::RegisterLocation(V0));
+  return summary;
 }
 
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  ASSERT(locs()->in(0).reg() == A0);  // Value.
+  ASSERT(locs()->in(1).reg() == A2);  // Instantiator.
+  ASSERT(locs()->in(2).reg() == A1);  // Instantiator type arguments.
+
+  __ Comment("InstanceOfInstr");
+  compiler->GenerateInstanceOf(token_pos(),
+                               deopt_id(),
+                               type(),
+                               negate_result(),
+                               locs());
+  ASSERT(locs()->out().reg() == V0);
 }
 
 
@@ -1739,14 +1860,19 @@
 
 LocationSummary*
 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  return MakeCallSummary();
 }
 
 
 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
     FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kAllocateObjectWithBoundsCheckRuntimeEntry,
+                                locs());
+  __ Drop(3);
+  ASSERT(locs()->out().reg() == V0);
+  __ Pop(V0);  // Pop new instance.
 }
 
 
@@ -1793,7 +1919,8 @@
   Label type_arguments_instantiated;
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawInstantiatedRaw(len)) {
-    __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated);
+    __ BranchEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
+                   &type_arguments_instantiated);
   }
   // Instantiate non-null type arguments.
   // A runtime call to instantiate the type arguments is required.
@@ -1846,7 +1973,8 @@
   // the type arguments.
   Label type_arguments_instantiated;
   ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
-  __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated);
+  __ BranchEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
+                 &type_arguments_instantiated);
   // Instantiate non-null type arguments.
   // In the non-factory case, we rely on the allocation stub to
   // instantiate the type arguments.
@@ -1886,7 +2014,8 @@
   // the type arguments and do not pass the instantiator.
   ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
   Label instantiator_not_null;
-  __ bne(instantiator_reg, NULLREG, &instantiator_not_null);
+  __ BranchNotEqual(instantiator_reg, reinterpret_cast<int32_t>(Object::null()),
+                    &instantiator_not_null);
   // Null was used in VisitExtractConstructorTypeArguments as the
   // instantiated type arguments, no proper instantiator needed.
   __ LoadImmediate(instantiator_reg,
@@ -2067,7 +2196,9 @@
     const intptr_t kCountLimit = 0x1F;
     const intptr_t value = Smi::Cast(constant).Value();
     if (value == 0) {
-      // No code needed.
+      if (result != left) {
+        __ mov(result, left);
+      }
     } else if ((value < 0) || (value >= kCountLimit)) {
       // This condition may not be known earlier in some cases because
       // of constant propagation, inlining, etc.
@@ -2101,6 +2232,7 @@
       const intptr_t left_int = Smi::Cast(obj).Value();
       if (left_int == 0) {
         __ bltz(right, deopt);
+        __ mov(result, ZR);
         return;
       }
       const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
@@ -2163,24 +2295,33 @@
 
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (op_kind() == Token::kTRUNCDIV) {
-    UNIMPLEMENTED();
-    return NULL;
-  } else {
-    const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
-    LocationSummary* summary =
-        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::RegisterOrSmiConstant(right()));
-    if (op_kind() == Token::kADD) {
-      // Need an extra temp for the overflow detection code.
-      summary->set_temp(0, Location::RequiresRegister());
+    if (RightIsPowerOfTwoConstant()) {
+      summary->set_in(0, Location::RequiresRegister());
+      ConstantInstr* right_constant = right()->definition()->AsConstant();
+      summary->set_in(1, Location::Constant(right_constant->value()));
+      summary->set_out(Location::RequiresRegister());
+    } else {
+      // Both inputs must be writable because they will be untagged.
+      summary->set_in(0, Location::WritableRegister());
+      summary->set_in(1, Location::WritableRegister());
+      summary->set_out(Location::RequiresRegister());
     }
-    // We make use of 3-operand instructions by not requiring result register
-    // to be identical to first input register as on Intel.
-    summary->set_out(Location::RequiresRegister());
     return summary;
   }
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  if (op_kind() == Token::kADD) {
+    // Need an extra temp for the overflow detection code.
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
@@ -2251,7 +2392,33 @@
         break;
       }
       case Token::kTRUNCDIV: {
-        UNIMPLEMENTED();
+        const intptr_t value = Smi::Cast(constant).Value();
+        if (value == 1) {
+          if (result != left) {
+            __ mov(result, left);
+          }
+          break;
+        } else if (value == -1) {
+          // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+          // case we cannot negate the result.
+          __ BranchEqual(left, 0x80000000, deopt);
+          __ subu(result, ZR, left);
+          break;
+        }
+        ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
+        const intptr_t shift_count =
+            Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
+        ASSERT(kSmiTagSize == 1);
+        __ sra(TMP, left, 31);
+        ASSERT(shift_count > 1);  // 1, -1 case handled above.
+        __ sll(TMP, TMP, 32 - shift_count);
+        __ addu(left, left, TMP);
+        ASSERT(shift_count > 0);
+        __ sra(result, left, shift_count);
+        if (value < 0) {
+          __ subu(result, ZR, result);
+        }
+        __ SmiTag(result);
         break;
       }
       case Token::kBIT_AND: {
@@ -2293,7 +2460,9 @@
 
         if (value == 0) {
           // TODO(vegorov): should be handled outside.
-          __ break_(0);
+          if (result != left) {
+            __ mov(result, left);
+          }
           break;
         } else if (value < 0) {
           // TODO(vegorov): should be handled outside.
@@ -2366,7 +2535,16 @@
       break;
     }
     case Token::kTRUNCDIV: {
-      UNIMPLEMENTED();
+      // Handle divide by zero in runtime.
+      __ beq(right, ZR, deopt);
+      __ SmiUntag(left);
+      __ SmiUntag(right);
+      __ div(left, right);
+      __ mflo(result);
+      // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+      // case we cannot tag the result.
+      __ BranchEqual(V0, 0x40000000, deopt);
+      __ SmiTag(result);
       break;
     }
     case Token::kSHR: {
@@ -2399,35 +2577,142 @@
 
 
 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+    new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  return summary;
 }
 
 
 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  Register left = locs()->in(0).reg();
+  Register right = locs()->in(1).reg();
+  if (left_cid == kSmiCid) {
+    __ andi(CMPRES, right, Immediate(kSmiTagMask));
+  } else if (right_cid == kSmiCid) {
+    __ andi(CMPRES, left, Immediate(kSmiTagMask));
+  } else {
+    __ or_(TMP, left, right);
+    __ andi(CMPRES, TMP, Immediate(kSmiTagMask));
+  }
+  __ beq(CMPRES, ZR, deopt);
 }
 
 
 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs,
+                          kNumTemps,
+                          LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+  explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    if (locs->out().reg() != V0) {
+      __ mov(locs->out().reg(), V0);
+    }
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  BoxDoubleInstr* instruction_;
+};
+
+
 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  Register out_reg = locs()->out().reg();
+  DRegister value = locs()->in(0).fpu_reg();
+
+  __ TryAllocate(compiler->double_class(),
+                 slow_path->entry_label(),
+                 out_reg);
+  __ Bind(slow_path->exit_label());
+  __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
 }
 
 
 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool needs_writable_input = (value_cid == kSmiCid);
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, needs_writable_input
+                     ? Location::WritableRegister()
+                     : Location::RequiresRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register value = locs()->in(0).reg();
+  const DRegister result = locs()->out().fpu_reg();
+
+  if (value_cid == kDoubleCid) {
+    __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
+  } else if (value_cid == kSmiCid) {
+    __ SmiUntag(value);  // Untag input before conversion.
+    __ mtc1(value, STMP1);
+    __ cvtdw(result, STMP1);
+  } else {
+    Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
+    Label is_smi, done;
+
+    __ andi(CMPRES, value, Immediate(kSmiTagMask));
+    __ beq(CMPRES, ZR, &is_smi);
+    __ LoadClassId(TMP, value);
+    __ BranchNotEqual(TMP, kDoubleCid, deopt);
+    __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
+    __ b(&done);
+    __ Bind(&is_smi);
+    // TODO(regis): Why do we preserve value here but not above?
+    __ sra(TMP, value, 1);
+    __ mtc1(TMP, STMP1);
+    __ cvtdw(result, STMP1);
+    __ Bind(&done);
+  }
 }
 
 
@@ -2476,13 +2761,28 @@
 
 
 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  DRegister left = locs()->in(0).fpu_reg();
+  DRegister right = locs()->in(1).fpu_reg();
+  DRegister result = locs()->out().fpu_reg();
+  switch (op_kind()) {
+    case Token::kADD: __ addd(result, left, right); break;
+    case Token::kSUB: __ subd(result, left, right); break;
+    case Token::kMUL: __ muld(result, left, right); break;
+    case Token::kDIV: __ divd(result, left, right); break;
+    default: UNREACHABLE();
+  }
 }
 
 
@@ -2707,24 +3007,56 @@
 
 
 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register value = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  switch (op_kind()) {
+    case Token::kNEGATE: {
+      Label* deopt = compiler->AddDeoptStub(deopt_id(),
+                                            kDeoptUnaryOp);
+      __ SubuDetectOverflow(result, ZR, value, CMPRES);
+      __ bltz(CMPRES, deopt);
+      break;
+    }
+    case Token::kBIT_NOT:
+      __ nor(result, value, ZR);
+      __ addiu(result, result, Immediate(-1));  // Remove inverted smi-tag.
+      break;
+    default:
+      UNREACHABLE();
+  }
 }
 
 
 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::WritableRegister());
+  result->set_out(Location::RequiresFpuRegister());
+  return result;
 }
 
 
 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register value = locs()->in(0).reg();
+  FpuRegister result = locs()->out().fpu_reg();
+  __ SmiUntag(value);
+  __ mtc1(value, STMP1);
+  __ cvtdw(result, STMP1);
 }
 
 
@@ -2762,13 +3094,34 @@
 
 
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  ASSERT((InputCount() == 1) || (InputCount() == 2));
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
+  result->set_in(0, Location::FpuRegisterLocation(D6));
+  if (InputCount() == 2) {
+    result->set_in(1, Location::FpuRegisterLocation(D7));
+  }
+  result->set_out(Location::FpuRegisterLocation(D0));
+  return result;
 }
 
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  // For pow-function return NAN if exponent is NAN.
+  Label do_call, skip_call;
+  if (recognized_kind() == MethodRecognizer::kDoublePow) {
+    DRegister exp = locs()->in(1).fpu_reg();
+    __ cund(exp, exp);
+    __ bc1f(&do_call);
+    // Exponent is NaN, return NaN.
+    __ movd(locs()->out().fpu_reg(), exp);
+    __ b(&skip_call);
+  }
+  __ Bind(&do_call);
+  // double values are passed and returned in vfp registers.
+  __ CallRuntime(TargetFunction());
+  __ Bind(&skip_call);
 }
 
 
@@ -2844,7 +3197,8 @@
   if (null_check()) {
     Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                           kDeoptCheckClass);
-    __ beq(locs()->in(0).reg(), NULLREG, deopt);
+    __ BranchEqual(locs()->in(0).reg(),
+        reinterpret_cast<int32_t>(Object::null()), deopt);
     return;
   }
 
@@ -3131,6 +3485,7 @@
 // Special code for numbers (compare values instead of references.)
 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ TraceSimMsg("StrictCompareInstr");
+  __ Comment("StrictCompareInstr");
   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
   Location left = locs()->in(0);
   Location right = locs()->in(1);
@@ -3281,6 +3636,7 @@
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ TraceSimMsg("AllocateObjectInstr");
+  __ Comment("AllocateObjectInstr");
   const Class& cls = Class::ZoneHandle(constructor().Owner());
   const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
   const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
@@ -3298,6 +3654,7 @@
 
 
 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Comment("CreateClosureInstr");
   const Function& closure_function = function();
   ASSERT(!closure_function.IsImplicitStaticClosureFunction());
   const Code& stub = Code::Handle(
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 9ba29ff..4f8588b 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -109,19 +109,20 @@
                               FieldAddress(T0, Array::length_offset()),
                               T2);
 
+  __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
   // Initialize all array elements to raw_null.
   // T0: new object start as a tagged pointer.
   // T1: new object end address.
   // T2: iterator which initially points to the start of the variable
   // data area to be initialized.
-  // NULLREG: null
+  // T7: null
   __ AddImmediate(T2, T0, sizeof(RawArray) - kHeapObjectTag);
 
   Label done;
   Label init_loop;
   __ Bind(&init_loop);
   __ BranchUnsignedGreaterEqual(T2, T1, &done);
-  __ sw(NULLREG, Address(T2, 0));
+  __ sw(T7, Address(T2, 0));
   __ b(&init_loop);
   __ delay_slot()->addiu(T2, T2, Immediate(kWordSize));
   __ Bind(&done);
@@ -201,13 +202,14 @@
     __ lw(T2, Address(SP, 0 * kWordSize));  // Value.
 
     // Null value is valid for any type.
-    __ beq(T2, NULLREG, &checked_ok);
+    __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+    __ beq(T2, T7, &checked_ok);
     __ delay_slot()->lw(T1, Address(SP, 2 * kWordSize));  // Array.
 
     __ lw(T1, FieldAddress(T1, type_args_field_offset));
 
     // T1: Type arguments of array.
-    __ beq(T1, NULLREG, &checked_ok);
+    __ beq(T1, T7, &checked_ok);
 
     // Check if it's dynamic.
     // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
@@ -462,8 +464,9 @@
   __ StoreIntoObject(T2,
                      FieldAddress(T1, Array::data_offset()),
                      T0);
+  __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
   __ Ret();
-  __ delay_slot()->mov(V0, NULLREG);
+  __ delay_slot()->mov(V0, T7);
   __ Bind(&fall_through);
   return false;
 }
@@ -836,7 +839,6 @@
 
 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
   Label fall_through;
-  __ Untested("Intrinsifier::Integer_bitXorFromInteger");
 
   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis.
   __ Ret();
@@ -1138,24 +1140,15 @@
 // returns false. Any non-double arg1 causes control flow to fall through to the
 // slow case (compiled method body).
 static bool CompareDoubles(Assembler* assembler, Condition true_condition) {
-  Label is_smi, no_conversion, no_NaN, fall_through;
+  Label is_smi, double_op, no_NaN, fall_through;
+  __ Comment("CompareDoubles Intrinsic");
 
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Both arguments are double, right operand is in T0.
-  __ lwc1(F2, FieldAddress(T0, Double::value_offset()));
-  __ b(&no_conversion);
-  __ delay_slot()->lwc1(F3,
-      FieldAddress(T0, Double::value_offset() + kWordSize));
-
-  __ Bind(&is_smi);
-  __ SmiUntag(T0);
-  __ mtc1(T0, F4);
-  __ cvtdw(D1, F4);
-
-  __ Bind(&no_conversion);
+  __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag);
+  __ Bind(&double_op);
   __ lw(T0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
-  __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
+  __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
   // Now, left is in D0, right is in D1.
 
   __ cund(D0, D1);  // Check for NaN.
@@ -1165,11 +1158,11 @@
   __ Bind(&no_NaN);
 
   switch (true_condition) {
-    case EQ: __ ceqd(D1, D0); break;
-    case LT: __ coltd(D1, D0); break;
-    case LE: __ coled(D1, D0); break;
-    case GT: __ coltd(D0, D1); break;
-    case GE: __ coled(D0, D1); break;
+    case EQ: __ ceqd(D0, D1); break;
+    case LT: __ coltd(D0, D1); break;
+    case LE: __ coled(D0, D1); break;
+    case GT: __ coltd(D1, D0); break;
+    case GE: __ coled(D1, D0); break;
     default: {
       // Only passing the above conditions to this function.
       UNREACHABLE();
@@ -1184,6 +1177,14 @@
   __ Bind(&is_true);
   __ LoadObject(V0, Bool::True());
   __ Ret();
+
+
+  __ Bind(&is_smi);
+  __ SmiUntag(T0);
+  __ mtc1(T0, STMP1);
+  __ cvtdw(D1, STMP1);
+  __ b(&double_op);
+
   __ Bind(&fall_through);
   return false;
 }
@@ -1268,7 +1269,6 @@
 // Left is double right is integer (Bigint, Mint or Smi)
 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
   Label fall_through;
-  __ Untested("Intrinsifier::Double_mulFromInteger");
   // Only Smi-s allowed.
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ andi(CMPRES, T0, Immediate(kSmiTagMask));
@@ -1320,7 +1320,7 @@
 
 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) {
   Label is_true;
-  __ Untested("Intrinsifier::Double_getIsNaN");
+
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
   __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
@@ -1337,7 +1337,6 @@
 
 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) {
   Label is_false, is_true, is_zero;
-  __ Untested("Intrinsifier::Double_getIsNegative");
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
   __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
@@ -1390,11 +1389,9 @@
 
 bool Intrinsifier::Math_sqrt(Assembler* assembler) {
   Label fall_through, is_smi, double_op;
-  __ Untested("Intrinsifier::Math_sqrt");
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Argument is double and is in T0.
-  __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
-  __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
+  __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag);
   __ Bind(&double_op);
   __ sqrtd(D0, D1);
   const Class& double_class = Class::Handle(
@@ -1447,8 +1444,6 @@
   ASSERT(Utils::IsUint(32, a_int_value));
   int32_t a_int32_value = static_cast<int32_t>(a_int_value);
 
-  __ Untested("Random_nextState");
-
   __ lw(T0, Address(SP, 0 * kWordSize));  // Receiver.
   __ lw(T1, FieldAddress(T0, state_field.Offset()));  // Field '_state'.
 
diff --git a/runtime/vm/runtime_entry_mips.cc b/runtime/vm/runtime_entry_mips.cc
index 622f24f..f9d2b2f 100644
--- a/runtime/vm/runtime_entry_mips.cc
+++ b/runtime/vm/runtime_entry_mips.cc
@@ -28,11 +28,17 @@
   uword entry = GetEntryPoint();
 #if defined(USING_SIMULATOR)
   // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
-  // in registers.
-  ASSERT(!is_leaf() || (argument_count() <= 4));
+  // in registers (maximum 2 double arguments for leaf float runtime calls).
+  ASSERT(argument_count() >= 0);
+  ASSERT(!is_leaf() ||
+         (!is_float() && (argument_count() <= 4)) ||
+         (argument_count() <= 2));
   Simulator::CallKind call_kind =
-      is_leaf() ? Simulator::kLeafRuntimeCall : Simulator::kRuntimeCall;
-  entry = Simulator::RedirectExternalReference(entry, call_kind);
+      is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
+                              : Simulator::kLeafRuntimeCall)
+                : Simulator::kRuntimeCall;
+  entry =
+      Simulator::RedirectExternalReference(entry, call_kind, argument_count());
 #endif
   if (is_leaf()) {
     ExternalLabel label(name(), entry);
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 3687bc9..0a12de3 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -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);
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index eca271d..9b685b2 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -106,9 +106,12 @@
   enum CallKind {
     kRuntimeCall,
     kLeafRuntimeCall,
+    kLeafFloatRuntimeCall,
     kNativeCall
   };
-  static uword RedirectExternalReference(uword function, CallKind call_kind);
+  static uword RedirectExternalReference(uword function,
+                                         CallKind call_kind,
+                                         int argument_count);
 
   void Longjmp(uword pc,
                uword sp,
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index e5cf95c..4bfd8a1 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -95,11 +95,11 @@
   // Load Context pointer from Isolate structure into A2.
   __ lw(A2, Address(CTX, Isolate::top_context_offset()));
 
-  // Reload NULLREG.
-  __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
+  // Load null.
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
 
   // Reset Context pointer in Isolate structure.
-  __ sw(NULLREG, Address(CTX, Isolate::top_context_offset()));
+  __ sw(TMP, Address(CTX, Isolate::top_context_offset()));
 
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, A2);
@@ -202,11 +202,11 @@
   // Load Context pointer from Isolate structure into A2.
   __ lw(A2, Address(CTX, Isolate::top_context_offset()));
 
-  // Reload NULLREG.
-  __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
+  // Load null.
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
 
   // Reset Context pointer in Isolate structure.
-  __ sw(NULLREG, Address(CTX, Isolate::top_context_offset()));
+  __ sw(TMP, Address(CTX, Isolate::top_context_offset()));
 
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, A2);
@@ -228,7 +228,8 @@
 
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S4, Address(SP, 1 * kWordSize));
-  __ sw(NULLREG, Address(SP, 0 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 0 * kWordSize));
 
   __ CallRuntime(kPatchStaticCallRuntimeEntry);
   __ TraceSimMsg("CallStaticFunctionStub return");
@@ -257,7 +258,8 @@
   // Setup space on stack for return value and preserve arguments descriptor.
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S4, Address(SP, 1 * kWordSize));
-  __ sw(NULLREG, Address(SP, 0 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 0 * kWordSize));
   __ CallRuntime(kFixCallersTargetRuntimeEntry);
   // Get Code object result and restore arguments descriptor array.
   __ lw(T0, Address(SP, 0 * kWordSize));
@@ -279,7 +281,7 @@
 static void PushArgumentsArray(Assembler* assembler) {
   __ TraceSimMsg("PushArgumentsArray");
   // Allocate array to store arguments of caller.
-  __ mov(A0, NULLREG);
+  __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null()));
   // A0: Null element type for raw Array.
   // A1: Smi-tagged argument count, may be zero.
   __ BranchLink(&StubCode::AllocateArrayLabel());
@@ -329,7 +331,8 @@
   // Push TMP1 data object.
   // Push arguments descriptor array.
   __ addiu(SP, SP, Immediate(-4 * kWordSize));
-  __ sw(NULLREG, Address(SP, 3 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 3 * kWordSize));
   __ sw(T1, Address(SP, 2 * kWordSize));
   __ sw(S5, Address(SP, 1 * kWordSize));
   __ sw(S4, Address(SP, 0 * kWordSize));
@@ -498,8 +501,44 @@
 
 
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ Unimplemented("MegamorphicMiss stub");
-  return;
+  __ EnterStubFrame();
+
+  // Load the receiver.
+  __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+  __ sll(T2, T2, 1);  // T2 is a Smi.
+  __ addu(TMP, FP, T2);
+  __ lw(T6, Address(TMP, kParamEndSlotFromFp * kWordSize));
+
+  // Preserve IC data and arguments descriptor.
+  __ addiu(SP, SP, Immediate(-6 * kWordSize));
+  __ sw(S5, Address(SP, 5 * kWordSize));
+  __ sw(S4, Address(SP, 4 * kWordSize));
+
+  // Push space for the return value.
+  // Push the receiver.
+  // Push IC data object.
+  // Push arguments descriptor array.
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 3 * kWordSize));
+  __ sw(T6, Address(SP, 2 * kWordSize));
+  __ sw(S5, Address(SP, 1 * kWordSize));
+  __ sw(S4, Address(SP, 0 * kWordSize));
+
+  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
+
+  __ lw(T0, Address(SP, 3 * kWordSize));  // Get result.
+  __ lw(S4, Address(SP, 4 * kWordSize));  // Restore argument descriptor.
+  __ lw(S5, Address(SP, 5 * kWordSize));  // Restore IC data.
+  __ addiu(SP, SP, Immediate(6 * kWordSize));
+
+  __ LeaveStubFrame();
+
+  Label nonnull;
+  __ BranchNotEqual(T0, reinterpret_cast<int32_t>(Object::null()), &nonnull);
+  __ Branch(&StubCode::InstanceFunctionLookupLabel());
+  __ Bind(&nonnull);
+  __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
+  __ jr(T0);
 }
 
 
@@ -604,12 +643,13 @@
     // T3: iterator which initially points to the start of the variable
     // data area to be initialized.
 
+    __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
     Label loop, loop_exit;
     __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit);
     __ Bind(&loop);
     __ addiu(T3, T3, Immediate(kWordSize));
     __ bne(T3, T2, &loop);
-    __ delay_slot()->sw(NULLREG, Address(T3, -kWordSize));
+    __ delay_slot()->sw(T7, Address(T3, -kWordSize));
     __ Bind(&loop_exit);
 
     // Done allocating and initializing the array.
@@ -627,17 +667,17 @@
   // Setup space on stack for return value.
   // Push array length as Smi and element type.
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ sw(NULLREG, Address(SP, 2 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 2 * kWordSize));
   __ sw(A1, Address(SP, 1 * kWordSize));
-  __ sw(T3, Address(SP, 0 * kWordSize));
+  __ sw(A0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kAllocateArrayRuntimeEntry);
   __ TraceSimMsg("AllocateArrayStub return");
   // Pop arguments; result is popped in IP.
-  __ lw(TMP1, Address(SP, 2 * kWordSize));
+  __ lw(V0, Address(SP, 2 * kWordSize));
   __ lw(A1, Address(SP, 1 * kWordSize));
-  __ lw(T3, Address(SP, 0 * kWordSize));
+  __ lw(A0, Address(SP, 0 * kWordSize));
   __ addiu(SP, SP, Immediate(3 * kWordSize));
-  __ mov(V0, TMP1);
 
   __ LeaveStubFrameAndReturn();
 }
@@ -666,8 +706,10 @@
   // Verify that T1 is a closure by checking its class.
   Label not_closure;
 
+  __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+
   // See if it is not a closure, but null object.
-  __ beq(T1, NULLREG, &not_closure);
+  __ beq(T1, T7, &not_closure);
 
   __ andi(CMPRES, T1, Immediate(kSmiTagMask));
   __ beq(CMPRES, ZR, &not_closure);  // Not a closure, but a smi.
@@ -678,7 +720,7 @@
   __ lw(T0, FieldAddress(T0, Class::signature_function_offset()));
 
   // See if actual class is not a closure class.
-  __ beq(T0, NULLREG, &not_closure);
+  __ beq(T0, T7, &not_closure);
 
   // T0 is just the signature function. Load the actual closure function.
   __ lw(T2, FieldAddress(T1, Closure::function_offset()));
@@ -689,7 +731,7 @@
   Label function_compiled;
   // Load closure function code in T0.
   __ lw(T0, FieldAddress(T2, Function::code_offset()));
-  __ bne(T0, NULLREG, &function_compiled);
+  __ bne(T0, T7, &function_compiled);
 
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
@@ -731,9 +773,9 @@
   __ EnterStubFrame();
 
   // Setup space on stack for result from error reporting.
-  __ addiu(SP, SP, Immediate(2 * kWordSize));
+  __ addiu(SP, SP, Immediate(-2 * kWordSize));
   // Arguments descriptor and raw null.
-  __ sw(NULLREG, Address(SP, 1 * kWordSize));
+  __ sw(T7, Address(SP, 1 * kWordSize));
   __ sw(S4, Address(SP, 0 * kWordSize));
 
   // Load smi-tagged arguments array length, including the non-closure.
@@ -825,9 +867,6 @@
   // Compute address of 'arguments array' data area into A2.
   __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle));
 
-  // Load the null Object into NULLREG for easy comparisons.
-  __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
-
   // Set up arguments for the Dart call.
   Label push_arguments;
   Label done_push_arguments;
@@ -960,20 +999,22 @@
     // T2: isolate, not an object.
     __ sw(T2, FieldAddress(V0, Context::isolate_offset()));
 
+    __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+
     // Initialize the context variables.
     // V0: new object.
     // T1: number of context variables.
     Label loop, loop_exit;
     __ blez(T1, &loop_exit);
     // Setup the parent field.
-    __ delay_slot()->sw(NULLREG, FieldAddress(V0, Context::parent_offset()));
+    __ delay_slot()->sw(T7, FieldAddress(V0, Context::parent_offset()));
     __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag);
     __ sll(T1, T1, 2);
     __ Bind(&loop);
     __ addiu(T1, T1, Immediate(-kWordSize));
     __ addu(TMP1, T3, T1);
     __ bgtz(T1, &loop);
-    __ delay_slot()->sw(NULLREG, Address(TMP1));
+    __ delay_slot()->sw(T7, Address(TMP1));
     __ Bind(&loop_exit);
 
     // Done allocating and initializing the context.
@@ -988,7 +1029,8 @@
   // Setup space on stack for return value.
   __ SmiTag(T1);
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(NULLREG, Address(SP, 1 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 1 * kWordSize));  // Store null.
   __ sw(T1, Address(SP, 0 * kWordSize));
   __ CallRuntime(kAllocateContextRuntimeEntry);  // Allocate context.
   __ lw(V0, Address(SP, 1 * kWordSize));  // Get the new context.
@@ -1172,6 +1214,8 @@
     __ LoadImmediate(T0, tags);
     __ sw(T0, Address(T2, Instance::tags_offset()));
 
+    __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+
     // Initialize the remaining words of the object.
     // T2: new object start.
     // T3: next object start.
@@ -1183,7 +1227,7 @@
       for (intptr_t current_offset = sizeof(RawObject);
            current_offset < instance_size;
            current_offset += kWordSize) {
-        __ sw(NULLREG, Address(T2, current_offset));
+        __ sw(T7, Address(T2, current_offset));
       }
     } else {
       __ addiu(T4, T2, Immediate(sizeof(RawObject)));
@@ -1197,7 +1241,7 @@
       __ Bind(&loop);
       __ addiu(T4, T4, Immediate(kWordSize));
       __ bne(T4, T3, &loop);
-      __ delay_slot()->sw(NULLREG, Address(T4, -kWordSize));
+      __ delay_slot()->sw(T7, Address(T4, -kWordSize));
       __ Bind(&loop_exit);
     }
     if (is_cls_parameterized) {
@@ -1223,7 +1267,8 @@
 
   __ addiu(SP, SP, Immediate(-4 * kWordSize));
   // Space on stack for return value.
-  __ sw(NULLREG, Address(SP, 3 * kWordSize));
+  __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(T7, Address(SP, 3 * kWordSize));
   __ sw(TMP1, Address(SP, 2 * kWordSize));  // Class of object to be allocated.
 
   if (is_cls_parameterized) {
@@ -1233,7 +1278,7 @@
   } else {
     // Push null type arguments and kNoInstantiator.
     __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator));
-    __ sw(NULLREG, Address(SP, 1 * kWordSize));
+    __ sw(T7, Address(SP, 1 * kWordSize));
     __ sw(T1, Address(SP, 0 * kWordSize));
   }
   __ CallRuntime(kAllocateObjectRuntimeEntry);  // Allocate object.
@@ -1264,8 +1309,8 @@
 
   __ TraceSimMsg("AllocationStubForClosure");
   __ EnterStubFrame(true);  // Uses pool pointer to refer to function.
-  const intptr_t kTypeArgumentsFPOffset = 4 * kWordSize;
-  const intptr_t kReceiverFPOffset = 5 * kWordSize;
+  const intptr_t kTypeArgumentsFPOffset = 3 * kWordSize;
+  const intptr_t kReceiverFPOffset = 4 * kWordSize;
   const intptr_t closure_size = Closure::InstanceSize();
   const intptr_t context_size = Context::InstanceSize(1);  // Captured receiver.
   if (FLAG_inline_alloc &&
@@ -1337,7 +1382,8 @@
       __ sw(T0, Address(T4, Context::isolate_offset()));
 
       // Set the parent to null.
-      __ sw(NULLREG, Address(T4, Context::parent_offset()));
+      __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+      __ sw(TMP, Address(T4, Context::parent_offset()));
 
       // Initialize the context variable to the receiver.
       __ lw(T0, Address(FP, kReceiverFPOffset));
@@ -1370,24 +1416,24 @@
     num_slots = is_implicit_instance_closure ? 4 : 3;
   }
   __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
-  __ LoadObject(TMP1, func);
   // Setup space on stack for return value.
-  __ sw(NULLREG, Address(SP, (num_slots - 1) * kWordSize));
+  __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(T7, Address(SP, (num_slots - 1) * kWordSize));
+  __ LoadObject(TMP1, func);
   __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize));
   if (is_implicit_static_closure) {
     __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry);
     __ TraceSimMsg("AllocationStubForClosure return");
   } else {
+    __ mov(T2, T7);
     if (is_implicit_instance_closure) {
       __ lw(T1, Address(FP, kReceiverFPOffset));
       __ sw(T1, Address(SP, (num_slots - 3) * kWordSize));  // Receiver.
-      __ sw(NULLREG, Address(SP, (num_slots - 4) * kWordSize));  // Push null.
     }
     if (has_type_arguments) {
-      __ lw(V0, Address(FP, kTypeArgumentsFPOffset));
-      // Push type arguments of closure.
-      __ sw(V0, Address(SP, (num_slots - 3) * kWordSize));
+      __ lw(T2, Address(FP, kTypeArgumentsFPOffset));
     }
+    __ sw(T2, Address(SP, 0 * kWordSize));
 
     if (is_implicit_instance_closure) {
       __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry);
@@ -1407,8 +1453,37 @@
 }
 
 
+// The target function was not found, so invoke method
+// "dynamic noSuchMethod(Invocation invocation)".
+//  S5: inline cache data object.
+//  S4: arguments descriptor array.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
-  __ Unimplemented("CallNoSuchMethodFunction stub");
+  __ EnterStubFrame();
+
+  // Load the receiver.
+  __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+  __ sll(TMP, A1, 1);  // A1 is a Smi.
+  __ addu(TMP, FP, TMP);
+  __ lw(T6, Address(TMP, kParamEndSlotFromFp * kWordSize));
+
+  // Push space for the return value.
+  // Push the receiver.
+  // Push IC data object.
+  // Push arguments descriptor array.
+  __ addiu(SP, SP, Immediate(-4 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 3 * kWordSize));
+  __ sw(T6, Address(SP, 2 * kWordSize));
+  __ sw(S5, Address(SP, 1 * kWordSize));
+  __ sw(S4, Address(SP, 0 * kWordSize));
+
+  // A1: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+
+  __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry);
+
+  __ lw(V0, Address(SP, 4 * kWordSize));  // Get result into V0.
+  __ LeaveStubFrameAndReturn();
 }
 
 
@@ -1585,7 +1660,8 @@
   __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
   __ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
   __ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
-  __ sw(NULLREG, Address(SP, (num_slots - 3) * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, (num_slots - 3) * kWordSize));
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
     __ lw(TMP1, Address(T1, -i * kWordSize));
@@ -1615,7 +1691,8 @@
   __ addiu(SP, SP, Immediate(num_slots * kWordSize));
   __ LeaveStubFrame();
   Label call_target_function;
-  __ bne(T3, NULLREG, &call_target_function);
+  __ BranchNotEqual(T3, reinterpret_cast<int32_t>(Object::null()),
+                    &call_target_function);
 
   // NoSuchMethod or closure.
   // Mark IC call that it may be a closure call that does not collect
@@ -1737,7 +1814,8 @@
   // Preserve arguments descriptor and make room for result.
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S4, Address(SP, 1 * kWordSize));
-  __ sw(NULLREG, Address(SP, 0 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 0 * kWordSize));
   __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
   // Pop code object result and restore arguments descriptor.
   __ lw(T0, Address(SP, 0 * kWordSize));
@@ -1837,14 +1915,17 @@
   __ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset()));
   __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag);
 
+  __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+
   Label loop, found, not_found, next_iteration;
   // T0: instance class id.
   // T1: instance type arguments.
   // T2: Entry start.
+  // T7: null.
   __ SmiTag(T0);
   __ Bind(&loop);
   __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId));
-  __ beq(T3, NULLREG, &not_found);
+  __ beq(T3, T7, &not_found);
 
   if (n == 1) {
     __ beq(T3, T0, &found);
@@ -1868,7 +1949,7 @@
   // Fall through to not found.
   __ Bind(&not_found);
   __ Ret();
-  __ delay_slot()->mov(V0, NULLREG);
+  __ delay_slot()->mov(V0, T7);
 
   __ Bind(&found);
   __ Ret();
@@ -1947,6 +2028,7 @@
 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects.
 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) {
   __ TraceSimMsg("EqualityWithNullArgStub");
+  __ Comment("EqualityWithNullArgStub");
   __ EnterStubFrame();
   static const intptr_t kNumArgsTested = 2;
 #if defined(DEBUG)
@@ -2048,7 +2130,8 @@
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
   __ sw(S4, Address(SP, 2 * kWordSize));
   // Setup space on stack for return value.
-  __ sw(NULLREG, Address(SP, 1 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 1 * kWordSize));
   __ sw(T0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry);
   __ TraceSimMsg("OptimizeFunctionStub return");
@@ -2079,21 +2162,23 @@
 // cannot contain a value that fits in Mint or Smi.
 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
   __ TraceSimMsg("IdenticalWithNumberCheckStub");
-  const Register ret = CMPRES;
+  __ Comment("IdenticalWithNumberCheckStub");
   const Register temp1 = T2;
   const Register temp2 = T3;
   const Register left = T1;
   const Register right = T0;
   // Preserve left, right.
-  __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(T1, Address(SP, 1 * kWordSize));
-  __ sw(T0, Address(SP, 0 * kWordSize));
+  __ addiu(SP, SP, Immediate(-4 * kWordSize));
+  __ sw(temp1, Address(SP, 3 * kWordSize));
+  __ sw(temp2, Address(SP, 2 * kWordSize));
+  __ sw(left, Address(SP, 1 * kWordSize));
+  __ sw(right, Address(SP, 0 * kWordSize));
   // TOS + 3: left argument.
   // TOS + 2: right argument.
   // TOS + 1: saved left
   // TOS + 0: saved right
-  __ lw(left, Address(SP, 3 * kWordSize));
-  __ lw(right, Address(SP, 2 * kWordSize));
+  __ lw(left, Address(SP, 5 * kWordSize));
+  __ lw(right, Address(SP, 4 * kWordSize));
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ andi(temp1, left, Immediate(kSmiTagMask));
@@ -2106,48 +2191,50 @@
   __ LoadClassId(temp2, left);
   __ bne(temp1, temp2, &check_mint);
   __ LoadClassId(temp2, right);
-  __ subu(ret, temp1, temp2);
-  __ bne(ret, ZR, &done);
+  __ subu(CMPRES, temp1, temp2);
+  __ bne(CMPRES, ZR, &done);
 
   // Double values bitwise compare.
   __ lw(temp1, FieldAddress(left, Double::value_offset() + 0 * kWordSize));
-  __ lw(temp1, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
-  __ subu(ret, temp1, temp2);
-  __ bne(ret, ZR, &done);
+  __ lw(temp2, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
+  __ subu(CMPRES, temp1, temp2);
+  __ bne(CMPRES, ZR, &done);
   __ lw(temp1, FieldAddress(left, Double::value_offset() + 1 * kWordSize));
   __ lw(temp2, FieldAddress(right, Double::value_offset() + 1 * kWordSize));
   __ b(&done);
-  __ delay_slot()->subu(ret, temp1, temp2);
+  __ delay_slot()->subu(CMPRES, temp1, temp2);
 
   __ Bind(&check_mint);
   __ LoadImmediate(temp1, kMintCid);
   __ LoadClassId(temp2, left);
   __ bne(temp1, temp2, &check_bigint);
   __ LoadClassId(temp2, right);
-  __ subu(ret, temp1, temp2);
-  __ bne(ret, ZR, &done);
+  __ subu(CMPRES, temp1, temp2);
+  __ bne(CMPRES, ZR, &done);
 
   __ lw(temp1, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
   __ lw(temp2, FieldAddress(right, Mint::value_offset() + 0 * kWordSize));
-  __ subu(ret, temp1, temp2);
-  __ bne(ret, ZR, &done);
+  __ subu(CMPRES, temp1, temp2);
+  __ bne(CMPRES, ZR, &done);
   __ lw(temp1, FieldAddress(left, Mint::value_offset() + 1 * kWordSize));
   __ lw(temp2, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
   __ b(&done);
-  __ delay_slot()->subu(ret, temp1, temp2);
+  __ delay_slot()->subu(CMPRES, temp1, temp2);
 
   __ Bind(&check_bigint);
   __ LoadImmediate(temp1, kBigintCid);
   __ LoadClassId(temp2, left);
   __ bne(temp1, temp2, &reference_compare);
   __ LoadClassId(temp2, right);
-  __ subu(ret, temp1, temp2);
-  __ bne(ret, ZR, &done);
+  __ subu(CMPRES, temp1, temp2);
+  __ bne(CMPRES, ZR, &done);
 
-  __ EnterStubFrame(0);
+  __ EnterStubFrame();
   __ ReserveAlignedFrameSpace(2 * kWordSize);
-  __ sw(T1, Address(SP, 1 * kWordSize));
-  __ sw(T0, Address(SP, 0 * kWordSize));
+  __ sw(left, Address(SP, 1 * kWordSize));
+  __ sw(right, Address(SP, 0 * kWordSize));
+  __ mov(A0, left);
+  __ mov(A1, right);
   __ CallRuntime(kBigintCompareRuntimeEntry);
   __ TraceSimMsg("IdenticalWithNumberCheckStub return");
   // Result in V0, 0 means equal.
@@ -2156,14 +2243,16 @@
   __ delay_slot()->mov(CMPRES, V0);
 
   __ Bind(&reference_compare);
-  __ subu(ret, left, right);
+  __ subu(CMPRES, left, right);
   __ Bind(&done);
   // A branch or test after this comparison will check CMPRES == TMP1.
   __ mov(TMP1, ZR);
-  __ lw(T0, Address(SP, 0 * kWordSize));
-  __ lw(T1, Address(SP, 1 * kWordSize));
+  __ lw(right, Address(SP, 0 * kWordSize));
+  __ lw(left, Address(SP, 1 * kWordSize));
+  __ lw(temp2, Address(SP, 2 * kWordSize));
+  __ lw(temp1, Address(SP, 3 * kWordSize));
   __ Ret();
-  __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
+  __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize));
 }
 
 }  // namespace dart
diff --git a/tests/language/language.status b/tests/language/language.status
index 7554f25..e55fc34 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -553,4 +553,17 @@
 *: Skip
 
 [ $arch == simmips ]
-*: Skip
+arithmetic_test: Fail, Crash
+bit_operations_test: Crash, Fail
+char_escape_test: Pass, Crash
+deopt_smi_op_test: Fail
+div_with_power_of_two_test: Fail
+gc_test: Crash
+invocation_mirror_test: Fail
+load_to_load_forwarding_vm_test: Fail
+named_parameters_with_conversions_test: Pass, Crash
+positive_bit_operations_test: Pass, Fail, Crash
+left_shift_test: Pass, Fail
+large_implicit_getter_test: Crash, Pass
+stack_overflow_test: Crash, Pass
+stack_overflow_stacktrace_test: Crash, Pass